diff options
490 files changed, 70763 insertions, 19084 deletions
@@ -24,6 +24,14 @@ /kombu.db /server-log.txt +# pyconfigure/automake generated files +/Makefile +/autom4te.cache/ +/config.log +/config.status +/configure +/aclocal.m4 + # Tests /mediagoblin/tests/user_dev/ diff --git a/.gitmodules b/.gitmodules index e6a7464c..95a76e1f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,4 @@ [submodule "extlib/pdf.js"] path = extlib/pdf.js url = git://github.com/mozilla/pdf.js.git + @@ -4,5 +4,5 @@ source_file = mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po source_lang = en [main] -host = https://www.transifex.net +host = https://transifex.com @@ -8,60 +8,90 @@ variety of different ways and this software wouldn't exist without them. Thank you! * Aaron Williamson +* Aditi Mittal * Aeva Ntsc * Alejandro Villanueva * Aleksandar Micovic * Aleksej Serdjukov +* Alon Levy * Alex Camelio * András Veres-Szentkirályi +* Asheesh Laroia * Bassam Kurdali * Bernhard Keller +* Brandon Invergo * Brett Smith * Caleb Forbes Davis V * Corey Farwell * Chris Moylan * Christopher Allan Webber +* Dan Callahan +* David Thompson * Daniel Neel * Deb Nicholson +* Devan Goodwin * Derek Moore * Duncan Paterson * Elrond of Samba TNG * Emily O'Leary +* Gabi Thume +* Gabriel Saldana * Greg Grossmeier +* Hans Lo * Jakob Kramer * Jef van Schendel * Jessica Tallon * Jim Campbell * Joar Wandborg * Jorge Araya Navarro +* Josephine Bartholoma * Karen Rustad +* Kenneth Dombrowski +* Kushal Kumaran * Kuno Woudt +* Laura Arjona * Larisa Hoffenbecker +* Lenna Peterson * Luke Slater * Manuel Urbano Santos +* Marcel van der Boom * Mark Holmquist +* Mats Sjöberg * Matt Lee * Michele Azzolari +* Mike Linksvayer +* Natalie Foust-Pilcher * Nathan Yergler * Odin Hørthe Omdal * Osama Khalid * Pablo J. Urbano Santos +* Praveen Kumar * Rasmus Larsson +* Rodney Ewing * Runar Petursson * Sacha De'Angeli +* Sam Clegg * Sam Kleinman +* Sam Tuke * Sebastian Spaeth * Shawn Khan +* Simon Fondrie-Teitler * Stefano Zacchiroli +* sturm * Tiberiu C. Turbureanu * Tran Thanh Bao +* Tryggvi Björgvinsson * Shawn Khan +* Sergio Durigan Junior * Will Kahn-Greene -If you think your name should be on this list, let us know! +Special thanks to: + +* Starblessed of viewskew (lending server space!) +If you think your name should be on this list, let us know! We also are currently borrowing an image in mediagoblin/static/images/media_thumbs/image.png from the wonderful people at http://tango.freedesktop.org/ which is in the public -domain... thanks Tango folks!
\ No newline at end of file +domain... thanks Tango folks! diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..b9b91a0e --- /dev/null +++ b/Makefile.in @@ -0,0 +1,207 @@ +# Makefile.in +# +# Copyright © 2012, 2013 Brandon Invergo <brandon@invergo.net> +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. This file is offered as-is, +# without any warranty. + +# List whatever files you want to include in your source distribution here. +# You can include whole directories but note that *everything* under that +# directory will be included +DISTFILES = PKG-INFO Makefile.in configure setup.py install-sh + +DESTDIR = +VPATH = @srcdir@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_DISTNAME = ${PACKAGE_NAME}-${PACKAGE_VERSION} +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PYTHON = @PYTHON@ +VIRTUALENV = @VIRTUALENV@ +SPHINXBUILD = @SPHINXBUILD@ +POSTGRES = @POSTGRES@ +SHELL = @SHELL@ +MKDIR_P = @MKDIR_P@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +prefix = @prefix@ +srcdir = @srcdir@ +abs_srcdir = @abs_srcdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +pythondir = @pythondir@ +pyexecdir = @pyexecdir@ +pkgdatadir = $(datadir)/@PACKAGE_NAME@ +pkgincludedir = $(includedir)/@PACKAGE_NAME@ +pkgpythondir = @pkgpythondir@ +pkgpyexecdir = @pkgpyexecdir@ +PYTHONPATH = $(pythondir)$(PATH_SEPARATOR)$(DESTDIR)$(pythondir) + +all: develop + +.PHONY: all install develop uninstall distclean info install-html html \ +install-pdf pdf install-dvi dvi install-ps ps clean dist check \ +installdirs postgresql update + +# Since installing to a virtualenv is all the rage these days, support +# it here. If the VIRTUALENV variable is set to anything other than +# "no", set up a new virtualenv and install there, otherwise install +# as usual from setup.py +install: installdirs + $(NORMAL_INSTALL) +ifneq ($(VIRTUALENV),no) + $(VIRTUALENV) $(VIRTUALENV_FLAGS) --python=$(PYTHON) \ + --system-site-packages $(DESTDIR)$(prefix) || \ + $(VIRTUALENV) $(DESTDIR)$(prefix) + $(DESTDIR)$(prefix)/bin/python $(srcdir)/setup.py install \ + --prefix=$(DESTDIR)$(prefix) +else + $(PYTHON) $(srcdir)/setup.py install --prefix=$(DESTDIR)$(prefix) +endif + if [[ $(DESTDIR)$(prefix) != $(abs_srcdir) ]]; then \ + $(INSTALL_DATA) $(srcdir)/Makefile $(DESTDIR)$(prefix)/Makefile; \ + $(INSTALL_DATA) $(srcdir)/lazycelery.sh $(DESTDIR)$(prefix)/lazycelery.sh; \ + $(INSTALL_DATA) $(srcdir)/lazyserver.sh $(DESTDIR)$(prefix)/lazyserver.sh; \ + fi + +# The same as "install", except use the "develop" setup.py target +develop: installdirs + $(NORMAL_INSTALL) +ifneq ($(VIRTUALENV),no) + $(VIRTUALENV) $(VIRTUALENV_FLAGS) --python=$(PYTHON) \ + --system-site-packages $(DESTDIR)$(prefix) || \ + $(VIRTUALENV) $(DESTDIR)$(prefix) + $(DESTDIR)$(prefix)/bin/python $(srcdir)/setup.py develop \ + --prefix=$(DESTDIR)$(prefix) +else + $(PYTHON) $(srcdir)/setup.py develop --prefix=$(DESTDIR)$(prefix) +endif + if [ "$(DESTDIR)$(prefix)" != "$(abs_srcdir)" ]; then \ + $(INSTALL_DATA) $(srcdir)/Makefile $(DESTDIR)$(prefix)/Makefile; \ + $(INSTALL_DATA) $(srcdir)/lazycelery.sh $(DESTDIR)$(prefix)/lazycelery.sh; \ + $(INSTALL_DATA) $(srcdir)/lazyserver.sh $(DESTDIR)$(prefix)/lazyserver.sh; \ + fi + + +# setup.py doesn't (yet) support an uninstall command, so until it does, you +# must manually remove everything that was installed here. The following example +# should remove a basic package installed via setup.py, but please double- and +# triple-check it so that you don't remove something you shouldn't! +# Be sure to remove any extra files you install, such as binaries or documentation! +# uninstall: +# case $(prefix) in +# /usr|/usr/local ) +# exit 1 ;; +# /www/*|/srv/* ) +# rm -rvf $(prefix) ;; +# esac + +# Just use the usual setup.py clean command +clean: + $(PYTHON) setup.py clean + + +# Clean up the output of configure +distclean: + rm -v $(srcdir)/config.log + rm -v $(srcdir)/config.status + rm -rvf $(srcdir)/autom4te.cache + rm -v $(srcdir)/aclocal.m4 + rm -v $(srcdir)/Makefile + +# You can either use the setup.py sdist command or you can roll your own here +dist: +# $(PYTHON) setup.py sdist + mkdir $(PACKAGE_DISTNAME) + cp -r $(DISTFILES) $(PACKAGE_DISTNAME) + tar -czf $(PACKAGE_DISTNAME).tar.gz $(PACKAGE_DISTNAME) + rm -rf $(PACKAGE_DISTNAME) + +# Use the setup.py check command +check: + $(PYTHON) setup.py check + +# setup.py might complain if a directory doesn't exist so just in case, make the directory +# here +installdirs: + $(MKDIR_P) $(DESTDIR)$(prefix) + +# Set up PostgreSQL +postgresql: + sudo -u $(POSTGRES) createuser mediagoblin + sudo -u $(POSTGRES) createdb -E UNICODE -O mediagoblin mediagoblin + +update: +ifneq ($(VIRTUALENV),no) + $(prefix)/bin/python $(srcdir)/setup.py develop --prefix=$(prefix) --upgrade +else + $(PYTHON) $(srcdir)/setup.py develop --prefix=$(prefix) --upgrade +endif + $(prefix)/bin/gmg dbupdate + +# The following show how to install documentation. In this example, +# docs are built from a separate Makefile contained in the docs +# directory which uses the SPHINXBUILD variable to store the location +# of the sphinx-build (Python doc tool) binary to use. + +$(DESTDIR)$(infodir)/mediagoblin.info: docs/build/texinfo/mediagoblin.info + $(POST_INSTALL) + $(INSTALL_DATA) @< $(DESTDIR)$@ + if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then + install-info --dir-file=$(DESTDIR)$(infodir)/dir \ + $(DESTDIR)$(infodir)/foo.info; + else true; fi + +info: docs/build/texinfo/mediagoblin.info + +docs/build/texinfo/mediagoblin.info: $(wildcard docs/source/*) +ifneq ($(SPHINXBUILD),no) + $(MAKE) -C docs info SPHINXBUILD=$(SPHINXBUILD) +endif + + +install-html: html installdirs + $(INSTALL_DATA) docs/build/html/* $(DESTDIR)$(htmldir) + +html: docs/build/html/index.html + +docs/build/html/index.html: $(wildcard $(srcdir)/docs/source/*) +ifneq ($(SPHINXBUILD),no) + $(MAKE) -C docs html SPHINXBUILD=$(SPHINXBUILD) +endif + + +install-pdf: pdf installdirs + $(INSTALL_DATA) docs/build/latex/mediagoblin.pdf $(DESTDIR)$(pdfdir) + +pdf: docs/build/latex/mediagoblin.pdf + +docs/build/latex/mediagoblin.pdf: $(wildcard $(srcdir)/docs/source/*) +ifneq ($(SPHINXBUILD),no) + $(MAKE) -C docs latexpdf SPHINXBUILD=$(SPHINXBUILD) +endif + + +install-dvi: + +dvi: + +install-ps: + +ps: + + diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 00000000..24fb75b1 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,19 @@ +Metadata-Version: 1.2 +Name: mediagoblin +Version: 0.4.0.dev +Summary: UNKNOWN +Home-page: http://mediagoblin.org/ +Author: Free Software Foundation and contributors +Author-email: cwebber@gnu.org +License: AGPLv3 +Download-URL: http://mediagoblin.org/download/ +Description: +Platform: UNKNOWN +Classifier: Development Status :: 3 - Alpha +Classifier: Environment :: Web Environment +Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+) +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content @@ -5,21 +5,21 @@ 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) +* A place to store all your different media (photos, videos, audios, + and more!) that’s as awesome as, if not more awesome than, existing + network services (Flickr, YouTube, etc) * Customizable! * A place for people to collaborate and show off original and derived 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! +* Extensible: Plugins allow you to add new media types (3d models? + Presentations and documents? Yes, and more!) or extend old ones. +* A real community, and we'd love to have you join us! Is it ready for me to use? ========================== -Yes! But with caveats. The software is usable and there are instances -running, but it's still in its early stages. +Yes! Can I help/hang out/participate/whisper sweet nothings in your ear? diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 00000000..78d0f1c7 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +aclocal -I m4 --install +autoreconf -fvi diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..e56a55a5 --- /dev/null +++ b/configure.ac @@ -0,0 +1,202 @@ +dnl configure.ac +dnl +dnl Copyright 2012, 2013 Brandon Invergo <brandon@invergo.net> +dnl +dnl Copying and distribution of this file, with or without modification, +dnl are permitted in any medium without royalty provided the copyright +dnl notice and this notice are preserved. This file is offered as-is, +dnl without any warranty. + +dnl######### +dnl README # +dnl######### +dnl +dnl This is a basic Autoconf configure.ac file for Python-based +dnl projects. It is not intended to be used as-is, but rather to be +dnl modified to the specific needs of the project. +dnl +dnl Lines prefixed with "dnl" are comments that are automatically +dnl removed by Autoconf/M4, thus they will not appear in the generated +dnl configure script (see the M4 documentation for more information). +dnl Such comments are used in this file to communicate information to +dnl you, the developer. In some cases, the comments contain extra +dnl macros that you might consider including in your configure script. +dnl If you wish to include them, simply remove the "dnl" from the +dnl beginning of the line. +dnl +dnl Lines prefixed with "#" are comments that will appear in the +dnl generated configure script. These comments are thus used to clarify +dnl to the user what is happening in that script +dnl +dnl Wherever pyconfigure-specific macros are used, extra comments are +dnl included to describe the macros. + +dnl###################### +dnl Package Information # +dnl###################### + +dnl---- +dnl Initialize Autoconf with the package metadata +dnl The arguments have been set via the project's PKG-INFO file +dnl and correspond to: +dnl +dnl 1) package name (i.e. foo) +dnl 2) package version (i.e. 1.2) +dnl 3) bug/info/project email address (i.e. bug-foo@gnu.org) +dnl---- +dnl +AC_INIT([mediagoblin], [0.4.0.dev], [cwebber@gnu.org]) + +dnl---- +dnl Load macros from the m4/ directory. If you plan to write new +dnl macros, put them in files in this directory. +dnl---- +dnl +AC_CONFIG_MACRO_DIR([m4]) + + +# The default prefix should be changed from /usr/local. Set it, as in +# the documentation, to /srv/mediagoblin.example.org/mediagoblin/ +AC_PREFIX_DEFAULT([`pwd`]) + + +dnl########################### +dnl Program/command support # +dnl########################### +dnl +dnl In this section, we check for the presence of important commands +dnl and programs. + +dnl--PC_INIT---------------------------------------------------------- +dnl This is the only required macro. Its primary function is to find +dnl a Python interpreter that is compatible with the package and set +dnl the PYTHON variable to hold its path. It can optionally take +dnl arguments to specify minimum and/or maximum versions: +dnl PC_INIT: find an interpreter with a version between 2.0 and 3.3.99 +dnl (in other words, up to and including any possible release +dnl in the 3.3 series) +dnl PC_INIT([MIN_VER], [MAX_VER]): Find an interpreter that is between +dnl the minimum and maximum version. If the min is in the 2.0 +dnl series and the max is in the 3.0 series, non-existent +dnl releases (2.8 & 2.9) will be correctly skipped. +dnl---- +dnl +PC_INIT([2.6], [2.7.99]) + +dnl--PC_PYTHON_PROG_PYTHON_CONFIG------------------------------------- +dnl In order to use some of the other macros, you also need the +dnl python-config command, which will fall subject to the same problem +dnl of python3-config being preferred to python2-config. This macro +dnl will be automatically included if you use on of the macros that +dnl depends on it, so you normally don't have to call it. However, if +dnl you require a specific version, you can do something like the +dnl following example. +dnl---- +dnl +PC_PYTHON_PROG_PYTHON_CONFIG([python2-config]) +if [[ "x$PYTHON_CONFIG" == "x" ]]; then + PC_PYTHON_PROG_PYTHON_CONFIG([$PYTHON-config]) +fi + +dnl---- +dnl With the following set of macros, we implement an option +dnl "--with-virtualenv", which the user can pass to the configure +dnl script in order to install to a Virtualenv (AC_ARG_WITH). If the +dnl option is specified by the user, then we check if the program is +dnl available, checking both for "virtualenv" and "virtualenv2" +dnl (AC_CHECK_PROGS) +dnl---- +dnl +# Support installing to a virtualenv via the --with-virtualenv +# configure flag +AC_ARG_WITH([virtualenv], + [AS_HELP_STRING([--without-virtualenv], [install to a Python virtualenv])], + [], + [with_virtualenv=yes]) +AS_IF([test "x$with_virtualenv" != xno], + AC_CHECK_PROGS([VIRTUALENV], [virtualenv virtualenv3 virtualenv2], [no]) + AS_IF([test "x$VIRTUALENV" = xno], + [AC_MSG_FAILURE( + [--with-virtualenv given but virtualenv could not be found])]), + AC_SUBST([VIRTUALENV], [no])) +AC_ARG_VAR([VIRTUALENV_FLAGS], [flags to pass to the virtualenv command]) + +dnl---- +dnl If the program uses sphinx-build to build documentation, uncomment +dnl this to create a SPHINXBUILD variable in the Makefile pointing to +dnl the program. Thus, the user would specify +dnl SPHINXBUILD=/path/to/sphinx-build as an argument to the configure +dnl script. Since building the documentation should be optional, just +dnl print a warning. If the program uses some other documentation +dnl system, you can do something similar with it. +dnl---- +dnl +# Check for sphinx-build +AC_CHECK_PROGS([SPHINXBUILD], [sphinx-build sphinx-build3 sphinx-build2], [no]) +AS_IF([test "x$SPHINXBUILD" = xno], + AC_MSG_WARN(sphinx-build is required to build documentation)) + + +dnl---- +dnl These two are standard Autoconf macros which check for the +dnl presence of some programs that we will use in the Makefile. +dnl---- +dnl +AC_PROG_MKDIR_P +AC_PROG_INSTALL + +# Check for a supported database program +AC_PATH_PROG([SQLITE], [sqlite3]) +AC_PATH_PROG([POSTGRES], [postgres]) +AS_IF([test "x$SQLITE" = x -a "x$POSTGRES" = "x"], + [AC_MSG_ERROR([SQLite or PostgreSQL is required])]) + + +dnl--PC_PYTHON_SITE_PACKAGE_DIR--------------------------------------- +dnl This uses PYTHON_SITE_DIR to construct a directory for this +dnl project (ie $PYTHON_SITE_DIR/project_name) and stores it in +dnl pkgpythondir. This value is used by Automake for installing Python +dnl scripts. By default, this begins with $pythondir, unexpanded, to +dnl provide compatibility with GNU Makefile specifications, allowing +dnl the user to change the prefix from the commandline. +dnl---- +dnl +PC_PYTHON_SITE_PACKAGE_DIR + +dnl--PC_PYTHON_EXEC_PACKAGE_DIR---------------------------------------- +dnl Same as PC_PYTHON_SITE_PACKAGE_DIR but for $exec-prefix. Stored in +dnl pkgpyexecdir +dnl---- +dnl +PC_PYTHON_EXEC_PACKAGE_DIR + + +dnl############################### +dnl Checking Python capabilities # +dnl############################### + +dnl--PC_PYTHON_CHECK_MODULE([PYTHON-MODULE], [ACTION-IF-PRESENT], +dnl [ACTION-IF-ABSENT]) +dnl This macro lets you check if a given Python module exists on the +dnl system. +dnl---- +dnl +dnl PC_PYTHON_CHECK_MODULE([foo]) + +# Check for python-lxml module +PC_PYTHON_CHECK_MODULE([lxml], [], + [AC_MSG_ERROR([python-lxml is required])]) + +# Check for the Python Imaging Library +PC_PYTHON_CHECK_MODULE([Image], [], + [AC_MSG_ERROR([Python Imaging Library is required])]) + + +dnl######### +dnl Finish # +dnl######### + +dnl Define the files to be configured +AC_CONFIG_FILES([Makefile]) +dnl Generate config.status +AC_OUTPUT diff --git a/devtools/make_example_database.sh b/devtools/make_example_database.sh new file mode 100755 index 00000000..7e857f53 --- /dev/null +++ b/devtools/make_example_database.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 GNU 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/>. + +USAGE="Usage: $0 -h | [-p PATH] -e ENVIRONMENT" + +ENVIRONMENT="migration-18" +USER_DEV="user_dev_default" +DEV_ENV_DIRECTORY_PATH="../mg-dev-environments" + +while getopts ":hp:e:" opt; +do + case $opt in + h) + echo $USAGE + echo "Sets up an example mediagoblin instance for testing code." + echo "" + echo " -h Shows this help message." + echo " -p=PATH The path to your mg-dev-environments repository" + echo " -e=ENVIRONMENT The name of the environment you want to set up. Useful" + echo " if you want to set up a database from a past version." + echo " This defaults to a database from the most recent version" + echo " of master." + exit 1 + ;; + e) + ENVIRONMENT=$OPTARG + ;; + p) + DEV_ENV_DIRECTORY_PATH=$OPTARG + ;; + \?) + echo "Invalid Option: -$OPTARG" >&2 + ;; + :) + echo "Option -$OPTARG requires an argument" >&2 + ;; + esac +done + +if [ ! -d $DEV_ENV_DIRECTORY_PATH ]; then + echo "$DEV_ENV_DIRECTORY_PATH not found. Have you downloaded the repo from \ +git@gitorious.org:mediagoblin/mg-dev-environments.git ?" >&2 + echo "" + exit 1 +fi + +if [ ! -d "user_dev" ]; then + echo "ERROR: This script should be executed from within your mediagoblin \ +instance directory" >&2 + exit 1 +fi + +if [ ! -e "$DEV_ENV_DIRECTORY_PATH/$ENVIRONMENT.tar.gz" ]; then + echo "$ENVIRONMENT.tar.gz not found in directory $DEV_ENV_DIRECTORY_PATH" >&2 + exit 1 +else + echo "***WARNING!***" + echo "This script will WIPE YOUR FULL CURRENT ENVIRONMENT and REPLACE IT with a test database and media!" + echo "Your databases and user_dev/ will all likely be wiped!" + echo -n "Do you want to continue? (y/n) " + read -n1 USER_CONFIRM + echo "" + counter=0 + while [ "$USER_CONFIRM"=="y" ]; do + case $USER_CONFIRM in + y) + break + ;; + n) + exit 1 + ;; + *) + if [ $counter -lt 5 ]; then + echo "Invalid option. Please enter 'y' or 'n'" + echo "Do you want to continue? (y/n)" + read -n1 USER_CONFIRM + echo "" + counter+=1 + continue + else + exit 1 + fi + ;; + esac + done + tar -xzf $DEV_ENV_DIRECTORY_PATH/$ENVIRONMENT.tar.gz + tar -xzf $DEV_ENV_DIRECTORY_PATH/$USER_DEV.tar.gz + echo "Completed." + exit 0 +fi diff --git a/docs/source/api/client_register.rst b/docs/source/api/client_register.rst new file mode 100644 index 00000000..08f92c47 --- /dev/null +++ b/docs/source/api/client_register.rst @@ -0,0 +1,158 @@ +.. MediaGoblin Documentation + + Written in 2011, 2012 by MediaGoblin contributors + + To the extent possible under law, the author(s) have dedicated all + copyright and related and neighboring rights to this software to + the public domain worldwide. This software is distributed without + any warranty. + + You should have received a copy of the CC0 Public Domain + Dedication along with this software. If not, see + <http://creativecommons.org/publicdomain/zero/1.0/>. + +==================== +Registering a Client +==================== + +To use the GNU MediaGoblin API you need to use the dynamic client registration. This has been adapted from the `OpenID specification <https://openid.net/specs/openid-connect-registration-1_0.html>`_, this is the only part of OpenID that is being used to serve the purpose to provide the client registration which is used in OAuth. + +The endpoint is ``/api/client/register`` + +The parameters are: + +type + **required** - This must be either *client_associate* (for new registration) or *client_update* + +client_id + **update only** - This should only be used updating client information, this is the client_id given when you register + +client_secret + **update only** - This should only be used updating client information, this is the client_secret given when you register + +contacts + **optional** - This a space seporated list of email addresses to contact of people responsible for the client + +application_type + **required** - This is the type of client you are making, this must be either *web* or *native* + +application_name + **optional** - This is the name of your client + +logo_url + **optional** - This is a URL of the logo image for your client + +redirect_uri + **optional** - This is a space seporated list of pre-registered URLs for use at the Authorization Server + + +Response +-------- + +You will get back a response: + +client_id + This identifies a client + +client_secret + This is the secret. + +expires_at + This is time that the client credentials expire. If this is 0 the client registration does not expire. + +======= +Example +======= + +Register Client +--------------- + +To register a client for the first time, this is the minimum you must supply:: + + { + "type": "client_associate", + "application_type": "native" + } + +A Response will look like:: + + { + "client_secret": "hJtfhaQzgKerlLVdaeRAgmbcstSOBLRfgOinMxBCHcb", + "expires_at": 0, + "client_id": "vwljdhUMhhNbdKizpjZlxv" + } + + +Updating Client +--------------- + +Using the response we got above we can update the information and add new information we may have opted not to supply:: + + { + "type": "client_update", + "client_id": "vwljdhUMhhNbdKizpjZlxv", + "client_secret": "hJtfhaQzgKerlLVdaeRAgmbcstSOBLRfgOinMxBCHcb", + "application_type": "web", + "application_name": "MyClient!", + "logo_url": "https://myclient.org/images/my_logo.png", + "contacts": "myemail@someprovider.com another_developer@provider.net", + } + +The response will just return back the client_id and client_secret you sent:: + + { + "client_id": "vwljdhUMhhNbdKizpjZlxv", + "client_secret": "hJtfhaQzgKerlLVdaeRAgmbcstSOBLRfgOinMxBCHcb", + "expires_at": 0 + } + + +====== +Errors +====== + +There are a number of errors you could get back, This explains what could cause some of them: + +Could not decode data + This is caused when you have an error in the encoding of your data. + +Unknown Content-Type + You should sent a Content-Type header with when you make a request, this should be either application/json or www-form-urlencoded. This is caused when a unknown Content-Type is used. + +No registration type provided + This is when you leave out the ``type``. This should either be client_update or client_associate + +Unknown application_type. + This is when you have provided a ``type`` however this isn't one of the known types. + +client_id is required to update. + When you try and update you need to specify the client_id, this will be what you were given when you initially registered the client. + +client_secret is required to update. + When you try to update you need to specify the client_secrer, this will be what you were given when you initially register the client. + +Unauthorized. + This is when you are trying to update however the client_id and/or client_secret you have submitted are incorrect. + +Only set client_id for update. + This should only be given when you update. + +Only set client_secret for update. + This should only be given when you update. + +Logo URL <url> is not a valid URL + This is when the URL specified did not meet the validation. + +contacts must be a string of space-separated email addresses. + ``contacts`` should be a string (not a list), ensure each email is seporated by a space + +Email <email> is not a valid email + This is when you have submitted an invalid email address + +redirect_uris must be space-separated URLs. + ``redirect_uris`` should be a string (not a list), ensure each URL is seporated by a space + +URI <URI> is not a valid URI + This is when your URI is invalid. + + diff --git a/docs/source/api/oauth.rst b/docs/source/api/oauth.rst new file mode 100644 index 00000000..003ad492 --- /dev/null +++ b/docs/source/api/oauth.rst @@ -0,0 +1,36 @@ +.. MediaGoblin Documentation + + Written in 2011, 2012 by MediaGoblin contributors + + To the extent possible under law, the author(s) have dedicated all + copyright and related and neighboring rights to this software to + the public domain worldwide. This software is distributed without + any warranty. + + You should have received a copy of the CC0 Public Domain + Dedication along with this software. If not, see + <http://creativecommons.org/publicdomain/zero/1.0/>. + +============== +Authentication +============== + +GNU MediaGoblin uses OAuth1 to authenticate requests to the API. There are many +libraries out there for OAuth1, you're likely not going to have to do much. There +is a library for the GNU MediaGoblin called `PyPump <https://github.com/xray7224/PyPump>`_. +We are not using OAuth2 as we want to stay completely compatable with GNU MediaGoblin. + + +We use :doc:`client_register` to get the client ID and secret. + +Endpoints +--------- + +These are the endpoints you need to use for the oauth requests: + +`/oauth/request_token` is for getting the request token. + +`/oauth/authorize` is to send the user to to authorize your application. + +`/oauth/access_token` is for getting the access token to use in requests. + diff --git a/docs/source/devel/migrations.rst b/docs/source/devel/migrations.rst new file mode 100644 index 00000000..16c02b04 --- /dev/null +++ b/docs/source/devel/migrations.rst @@ -0,0 +1,62 @@ +.. MediaGoblin Documentation + + Written in 2011, 2012 by MediaGoblin contributors + + To the extent possible under law, the author(s) have dedicated all + copyright and related and neighboring rights to this software to + the public domain worldwide. This software is distributed without + any warranty. + + You should have received a copy of the CC0 Public Domain + Dedication along with this software. If not, see + <http://creativecommons.org/publicdomain/zero/1.0/>. + +========== +Migrations +========== + +So, about migrations. Every time we change the way the database +structure works, we need to add a migration so that people running +older codebases can have their databases updated to the new structure +when they run `./bin/gmg dbupdate`. + +The first time `./bin/gmg dbupdate` is run by a user, it creates the +tables at the current state that they're defined in models.py and sets +the migration number to the current migration... after all, migrations +only exist to get things to the current state of the db. After that, +every migration is run with dbupdate. + +There's a few things you need to know: + +- We use `sqlalchemy-migrate + <http://code.google.com/p/sqlalchemy-migrate/>`_. + See `their docs <https://sqlalchemy-migrate.readthedocs.org/>`_. +- `Alembic <https://bitbucket.org/zzzeek/alembic>`_ might be a better + choice than sqlalchemy-migrate now or in the future, but we + originally decided not to use it because it didn't have sqlite + support. It's not clear if that's changed. +- SQLAlchemy has two parts to it, the ORM and the "core" interface. + We DO NOT use the ORM when running migrations. Think about it: the + ORM is set up with an expectation that the models already reflect a + certain pattern. But if a person is moving from their old patern + and are running tools to *get to* the current pattern, of course + their current database structure doesn't match the state of the ORM! +- How to write migrations? Maybe there will be a tutorial here in the + future... in the meanwhile, look at existing migrations in + `mediagoblin/db/migrations.py` and look in + `mediagoblin/tests/test_sql_migrations.py` for examples. +- Common pattern: use `inspect_table` to get the current state + of the table before we run alterations on it. +- Make sure you set the RegisterMigration to be the next migration in + order. +- What happens if you're adding a *totally new* table? In this case, + you should copy the table in entirety as it exists into + migrations.py then create the tables based off of that... see + add_collection_tables. This is easier than reproducing the SQL by + hand. +- If you're writing a feature branch, you don't need to keep adding + migrations every time you change things around if your database + structure is in flux. Just alter your migrations so that they're + correct for the merge into master. + +That's it for now! Good luck! diff --git a/docs/source/index.rst b/docs/source/index.rst index 7f692d57..3ead6136 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -44,6 +44,7 @@ MediaGoblin website. It is written for site administrators. siteadmin/relnotes siteadmin/theming siteadmin/plugins + siteadmin/commandline-upload .. _core-plugin-section: @@ -56,9 +57,12 @@ Part 2: Core plugin documentation plugindocs/flatpagesfile plugindocs/sampleplugin - plugindocs/oauth plugindocs/trim_whitespace plugindocs/raven + plugindocs/basic_auth + plugindocs/openid + plugindocs/persona + plugindocs/ldap Part 3: Plugin Writer's Guide @@ -73,6 +77,9 @@ This guide covers writing new GNU MediaGoblin plugins. pluginwriter/quickstart pluginwriter/database pluginwriter/api + pluginwriter/tests + pluginwriter/media_type_hooks + pluginwriter/authhooks Part 4: Developer's Zone @@ -86,6 +93,7 @@ This chapter contains various information for developers. devel/codebase devel/storage devel/originaldesigndecisions + devel/migrations Indices and tables diff --git a/docs/source/plugindocs/basic_auth.rst b/docs/source/plugindocs/basic_auth.rst new file mode 100644 index 00000000..83492ac2 --- /dev/null +++ b/docs/source/plugindocs/basic_auth.rst @@ -0,0 +1,2 @@ +.. include:: ../../../mediagoblin/plugins/basic_auth/README.rst + diff --git a/docs/source/plugindocs/ldap.rst b/docs/source/plugindocs/ldap.rst new file mode 100644 index 00000000..3938c0c7 --- /dev/null +++ b/docs/source/plugindocs/ldap.rst @@ -0,0 +1,2 @@ +.. include:: ../../../mediagoblin/plugins/ldap/README.rst + diff --git a/docs/source/plugindocs/openid.rst b/docs/source/plugindocs/openid.rst new file mode 100644 index 00000000..045bf9d0 --- /dev/null +++ b/docs/source/plugindocs/openid.rst @@ -0,0 +1,2 @@ +.. include:: ../../../mediagoblin/plugins/openid/README.rst + diff --git a/docs/source/plugindocs/persona.rst b/docs/source/plugindocs/persona.rst new file mode 100644 index 00000000..2524127d --- /dev/null +++ b/docs/source/plugindocs/persona.rst @@ -0,0 +1,2 @@ +.. include:: ../../../mediagoblin/plugins/persona/README.rst + diff --git a/docs/source/plugindocs/raven.rst b/docs/source/plugindocs/raven.rst index 71e284d0..ae96f3f8 100644 --- a/docs/source/plugindocs/raven.rst +++ b/docs/source/plugindocs/raven.rst @@ -1,2 +1 @@ -.. _raven-setup: Set up the raven plugin .. include:: ../../../mediagoblin/plugins/raven/README.rst diff --git a/docs/source/pluginwriter/api.rst b/docs/source/pluginwriter/api.rst index 3a75d455..29adb691 100644 --- a/docs/source/pluginwriter/api.rst +++ b/docs/source/pluginwriter/api.rst @@ -11,6 +11,7 @@ Dedication along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. +.. _plugin-api-chapter: ========== Plugin API @@ -23,7 +24,27 @@ Authors are encouraged to develop plugins and work with the MediaGoblin community to keep them up to date, but this API will be a moving target for a few releases. -Please check the release notes for updates! +Please check the :ref:`release-notes` for updates! + + +How are hooks added? Where do I find them? +------------------------------------------- + +Much of this document talks about hooks, both as in terms of regular +hooks and template hooks. But where do they come from, and how can +you find a list of them? + +For the moment, the best way to find available hooks is to check the +source code itself. (Yes, we should start a more official hook +listing with descriptions soon.) But many hooks you may need do not +exist yet: what to do then? + +The plan at present is that we are adding hooks as people need them, +with community discussion. If you find that you need a hook and +MediaGoblin at present doesn't provide it at present, please +`http://mediagoblin.org/pages/join.html <talk to us>`_! We'll +evaluate what to do from there. + :mod:`pluginapi` Module ----------------------- @@ -31,4 +52,271 @@ Please check the release notes for updates! .. automodule:: mediagoblin.tools.pluginapi :members: get_config, register_routes, register_template_path, register_template_hooks, get_hook_templates, - hook_handle, hook_runall, hook_transform, + hook_handle, hook_runall, hook_transform + +Configuration +------------- + +Your plugin may define its own configuration defaults. + +Simply add to the directory of your plugin a config_spec.ini file. An +example might look like:: + + [plugin_spec] + some_string = string(default="blork") + some_int = integer(default=50) + +This means that when people enable your plugin in their config you'll +be able to provide defaults as well as type validation. + +You can access this via the app_config variables in mg_globals, or you +can use a shortcut to get your plugin's config section:: + + >>> from mediagoblin.tools import pluginapi + # Replace with the path to your plugin. + # (If an external package, it won't be part of mediagoblin.plugins) + >>> floobie_config = pluginapi.get_config('mediagoblin.plugins.floobifier') + >>> floobie_dir = floobie_config['floobie_dir'] + # This is the same as the above + >>> from mediagoblin import mg_globals + >>> config = mg_globals.global_config['plugins']['mediagoblin.plugins.floobifier'] + >>> floobie_dir = floobie_config['floobie_dir'] + +A tip: you have access to the `%(here)s` variable in your config, +which is the directory that the user's mediagoblin config is running +out of. So for example, your plugin may need a "floobie" directory to +store floobs in. You could give them a reasonable default that makes +use of the default `user_dev` location, but allow users to override +it, like so:: + + [plugin_spec] + floobie_dir = string(default="%(here)s/user_dev/floobs/") + +Note, this is relative to the user's mediagoblin config directory, +*not* your plugin directory! + + +Context Hooks +------------- + +View specific hooks ++++++++++++++++++++ + +You can hook up to almost any template called by any specific view +fairly easily. As long as the view directly or indirectly uses the +method ``render_to_response`` you can access the context via a hook +that has a key in the format of the tuple:: + + (view_symbolic_name, view_template_path) + +Where the "view symbolic name" is the same parameter used in +``request.urlgen()`` to look up the view. So say we're wanting to add +something to the context of the user's homepage. We look in +mediagoblin/user_pages/routing.py and see:: + + add_route('mediagoblin.user_pages.user_home', + '/u/<string:user>/', + 'mediagoblin.user_pages.views:user_home') + +Aha! That means that the name is ``mediagoblin.user_pages.user_home``. +Okay, so then we look at the view at the +``mediagoblin.user_pages.user_home`` method:: + + @uses_pagination + def user_home(request, page): + # [...] whole bunch of stuff here + return render_to_response( + request, + 'mediagoblin/user_pages/user.html', + {'user': user, + 'user_gallery_url': user_gallery_url, + 'media_entries': media_entries, + 'pagination': pagination}) + +Nice! So the template appears to be +``mediagoblin/user_pages/user.html``. Cool, that means that the key +is:: + + ("mediagoblin.user_pages.user_home", + "mediagoblin/user_pages/user.html") + +The context hook uses ``hook_transform()`` so that means that if we're +hooking into it, our hook will both accept one argument, ``context``, +and should return that modified object, like so:: + + def add_to_user_home_context(context): + context['foo'] = 'bar' + return context + + hooks = { + ("mediagoblin.user_pages.user_home", + "mediagoblin/user_pages/user.html"): add_to_user_home_context} + + +Global context hooks +++++++++++++++++++++ + +If you need to add something to the context of *every* view, it is not +hard; there are two hooks hook that also uses hook_transform (like the +above) but make available what you are providing to *every* view. + +Note that there is a slight, but critical, difference between the two. + +The most general one is the ``'template_global_context'`` hook. This +one is run only once, and is read into the global context... all views +will get access to what are in this dict. + +The slightly more expensive but more powerful one is +``'template_context_prerender'``. This one is not added to the global +context... it is added to the actual context of each individual +template render right before it is run! Because of this you also can +do some powerful and crazy things, such as checking the request object +or other parts of the context before passing them on. + + +Adding static resources +----------------------- + +It's possible to add static resources for your plugin. Say your +plugin needs some special javascript and images... how to provide +them? Then how to access them? MediaGoblin has a way! + + +Attaching to the hook ++++++++++++++++++++++ + +First, you need to register your plugin's resources with the hook. +This is pretty easy actually: you just need to provide a function that +passes back a PluginStatic object. + +.. autoclass:: mediagoblin.tools.staticdirect.PluginStatic + + +Running plugin assetlink +++++++++++++++++++++++++ + +In order for your plugin assets to be properly served by MediaGoblin, +your plugin's asset directory needs to be symlinked into the directory +that plugin assets are served from. To set this up, run:: + + ./bin/gmg assetlink + + +Using staticdirect +++++++++++++++++++ + +Once you have this, you will want to be able to of course link to your +assets! MediaGoblin has a "staticdirect" tool; you want to use this +like so in your templates:: + + staticdirect("css/monkeys.css", "mystaticname") + +Replace "mystaticname" with the name you passed to PluginStatic. The +staticdirect method is, for convenience, attached to the request +object, so you can access this in your templates like: + +.. code-block:: html + + <img alt="A funny bunny" + src="{{ request.staticdirect('images/funnybunny.png', 'mystaticname') }}" /> + + +Additional hook tips +-------------------- + +This section aims to explain some tips in regards to adding hooks to +the MediaGoblin repository. + +WTForms hooks ++++++++++++++ + +We haven't totally settled on a way to tranform wtforms form objects, +but here's one way. In your view:: + + from mediagoblin.foo.forms import SomeForm + + def some_view(request) + form_class = hook_transform('some_form_transform', SomeForm) + form = form_class(request.form) + +Then to hook into this form, do something in your plugin like:: + + import wtforms + + class SomeFormAdditions(wtforms.Form): + new_datefield = wtforms.DateField() + + def transform_some_form(orig_form): + class ModifiedForm(orig_form, SomeFormAdditions) + return ModifiedForm + + hooks = { + 'some_form_transform': transform_some_form} + + +Interfaces +++++++++++ + +If you want to add a pseudo-interface, it's not difficult to do so. +Just write the interface like so:: + + class FrobInterface(object): + """ + Interface for Frobbing. + + Classes implementing this interface should provide defrob and frob. + They may also implement double_frob, but it is not required; if + not provided, we will use a general technique. + """ + + def defrob(self, frobbed_obj): + """ + Take a frobbed_obj and defrob it. Returns the defrobbed object. + """ + raise NotImplementedError() + + def frob(self, normal_obj): + """ + Take a normal object and frob it. Returns the frobbed object. + """ + raise NotImplementedError() + + def double_frob(self, normal_obj): + """ + Frob this object and return it multiplied by two. + """ + return self.frob(normal_obj) * 2 + + + def some_frob_using_method(): + # something something something + frobber = hook_handle(FrobInterface) + frobber.frob(blah) + + # alternately you could have a default + frobber = hook_handle(FrobInterface) or DefaultFrobber + frobber.defrob(foo) + + +It's fine to use your interface as the key instead of a string if you +like. (Usually this is messy, but since interfaces are public and +since you need to import them into your plugin anyway, interfaces +might as well be keys.) + +Then a plugin providing your interface can be like:: + + from mediagoblin.foo.frobfrogs import FrobInterface + from frogfrobber import utils + + class FrogFrobber(FrobInterface): + """ + Takes a frogputer science approach to frobbing. + """ + def defrob(self, frobbed_obj): + return utils.frog_defrob(frobbed_obj) + + def frob(self, normal_obj): + return utils.frog_frob(normal_obj) + + hooks = { + FrobInterface: lambda: return FrogFrobber} diff --git a/docs/source/pluginwriter/authhooks.rst b/docs/source/pluginwriter/authhooks.rst new file mode 100644 index 00000000..9721d729 --- /dev/null +++ b/docs/source/pluginwriter/authhooks.rst @@ -0,0 +1,86 @@ +====================== + Authentication Hooks +====================== + +This documents the hooks that are currently available for authentication +plugins. If you need new hooks for your plugin, go ahead a submit a patch. + +What hooks are available? +========================= + +'authentication' +---------------- + +This hook just needs to return ``True`` as this is how +the MediaGoblin app knows that an authentication plugin is enabled. + + +'auth_extra_validation' +----------------------- + +This hook is used to provide any additional validation of the registration +form when using ``mediagoblin.auth.tools.register_user()``. This hook runs +through all enabled auth plugins. + + +'auth_create_user' +------------------ + +This hook is used by ``mediagoblin.auth.tools.register_user()`` so plugins can +store the necessary information when creating a user. This hook runs through +all enabled auth plugins. + +'auth_get_user' +--------------- + +This hook is used by ``mediagoblin.auth.tools.check_login_simple()``. Your +plugin should return a ``User`` object given a username. + +'auth_no_pass_redirect' +----------------------- + +This hook is called in ``mediagoblin.auth.views`` in both the ``login`` and +``register`` views. This hook should return the name of your plugin, so that +if :ref:`basic_auth-chapter` is not enabled, the user will be redirected to the +correct login and registration views for your plugin. + +The code assumes that it can generate a valid url given +``mediagoblin.plugins.{{ your_plugin_here }}.login`` and +``mediagoblin.plugins.{{ your_plugin_here }}.register``. This is only needed if +you will not be using the ``login`` and ``register`` views in +``mediagoblin.auth.views``. + +'auth_get_login_form' +--------------------- + +This hook is called in ``mediagoblin.auth.views.login()``. If you are not using +that view, then you do not need this hook. This hook should take a ``request`` +object and return the ``LoginForm`` for your plugin. + +'auth_get_registration_form' +---------------------------- + +This hook is called in ``mediagoblin.auth.views.register()``. If you are not +using that view, then you do not need this hook. This hook should take a +``request`` object and return the ``RegisterForm`` for your plugin. + +'auth_gen_password_hash' +------------------------ + +This hook should accept a ``raw_pass`` and an ``extra_salt`` and return a +hashed password to be stored in ``User.pw_hash``. + +'auth_check_password' +--------------------- + +This hook should accept a ``raw_pass``, a ``stored_hash``, and an ``extra_salt``. +Your plugin should then check that the ``raw_pass`` hashes to the same thing as +the ``stored_hash`` and return either ``True`` or ``False``. + +'auth_fake_login_attempt' +------------------------- + +This hook is called in ``mediagoblin.auth.tools.check_login_simple``. It is +called if a user is not found and should do something that takes the same amount +of time as your ``check_password`` function. This is to help prevent timining +attacks. diff --git a/docs/source/pluginwriter/database.rst b/docs/source/pluginwriter/database.rst index 58edf3a0..603a19eb 100644 --- a/docs/source/pluginwriter/database.rst +++ b/docs/source/pluginwriter/database.rst @@ -12,9 +12,12 @@ <http://creativecommons.org/publicdomain/zero/1.0/>. -======== -Database -======== +.. _plugin-database-chapter: + + +=========================== +Database models for plugins +=========================== Accessing Existing Data diff --git a/docs/source/pluginwriter/media_type_hooks.rst b/docs/source/pluginwriter/media_type_hooks.rst new file mode 100644 index 00000000..498b0b54 --- /dev/null +++ b/docs/source/pluginwriter/media_type_hooks.rst @@ -0,0 +1,38 @@ +================== + Media Type hooks +================== + +This documents the hooks that are currently available for ``media_type`` plugins. + +What hooks are available? +========================= + +'sniff_handler' +--------------- + +This hook is used by ``sniff_media`` in ``mediagoblin.media_types.__init__``. +Your media type should return its ``sniff_media`` method when this hook is +called. + +.. Note:: + Your ``sniff_media`` method should return either the ``media_type`` or + ``None``. + +'get_media_type_and_manager' +---------------------------- + +This hook is used by ``get_media_type_and_manager`` in +``mediagoblin.media_types.__init__``. When this hook is called, your media type +plugin should check if it can handle the given extension. If so, your media +type plugin should return the media type and media manager. + +('media_manager', MEDIA_TYPE) +----------------------------- + +If you already know the string representing the media type of a type +of media, you can pull down the manager specifically. Note that this +hook is not a string but a tuple of two strings, the latter being the +name of the media type. + +This is used by media entries to pull down their media managers, and +so on. diff --git a/docs/source/pluginwriter/quickstart.rst b/docs/source/pluginwriter/quickstart.rst index b5a63f79..6d45ea36 100644 --- a/docs/source/pluginwriter/quickstart.rst +++ b/docs/source/pluginwriter/quickstart.rst @@ -178,8 +178,10 @@ That's it for the quick start! Where to go from here ===================== -See the documentation on the plugin API for code samples and other -things you can use when building your plugin. +See the documentation on the :ref:`plugin-api-chapter` for code +samples and other things you can use when building your plugin. If +your plugin needs its own database models, see +:ref:`plugin-database-chapter`. See `Hitchhiker's Guide to Packaging <http://guide.python-distribute.org/>`_ for more information on diff --git a/docs/source/pluginwriter/tests.rst b/docs/source/pluginwriter/tests.rst new file mode 100644 index 00000000..fe99688f --- /dev/null +++ b/docs/source/pluginwriter/tests.rst @@ -0,0 +1,64 @@ +.. MediaGoblin Documentation + + Written in 2013 by MediaGoblin contributors + + To the extent possible under law, the author(s) have dedicated all + copyright and related and neighboring rights to this software to + the public domain worldwide. This software is distributed without + any warranty. + + You should have received a copy of the CC0 Public Domain + Dedication along with this software. If not, see + <http://creativecommons.org/publicdomain/zero/1.0/>. + +============================== +Writing unit tests for plugins +============================== + +Here's a brief guide to writing unit tests for plugins. However, it +isn't really ideal. It also hasn't been well tested... yes, there's +some irony there :) + +Some notes: we're using py.test and webtest for unit testing stuff. +Keep that in mind. + +My suggestion is to mime the behavior of `mediagoblin/tests/` and put +that in your own plugin, like `myplugin/tests/`. Copy over +`conftest.py` and `pytest.ini` to your tests directory, but possibly +change the `test_app` fixture to match your own tests' config needs. +For example:: + + import pkg_resources + # [...] + + @pytest.fixture() + def test_app(request): + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'myplugin.tests', 'myplugin_mediagoblin.ini')) + +In any test module in your tests directory you can then do:: + + def test_somethingorother(test_app): + # real code goes here + pass + +And you'll get a mediagoblin application wrapped in webtest passed in +to your environment. + +If your plugin needs to define multiple configuration setups, you can +actually set up multiple fixtures very easily for this. You can just +set up multiple fixtures with different names that point to different +configs and pass them in as that named argument. + +To run the tests, from mediagoblin's directory (make sure that your +plugin has been added to your mediagoblin checkout's virtualenv!) do:: + + ./runtests.sh /path/to/myplugin/tests/ + +replacing `/path/to/myplugin/` with the actual path to your plugin. + +NOTE: again, the above is untested, but it should probably work. If +you run into trouble, `contact us +<http://mediagoblin.org/pages/join.html>`_, preferably on IRC! diff --git a/docs/source/siteadmin/commandline-upload.rst b/docs/source/siteadmin/commandline-upload.rst new file mode 100644 index 00000000..be19df58 --- /dev/null +++ b/docs/source/siteadmin/commandline-upload.rst @@ -0,0 +1,41 @@ +.. MediaGoblin Documentation + + Written in 2011, 2012 by MediaGoblin contributors + + To the extent possible under law, the author(s) have dedicated all + copyright and related and neighboring rights to this software to + the public domain worldwide. This software is distributed without + any warranty. + + You should have received a copy of the CC0 Public Domain + Dedication along with this software. If not, see + <http://creativecommons.org/publicdomain/zero/1.0/>. + +====================== +Command-line uploading +====================== + +Want to submit media via the command line? It's fairly easy to do:: + + ./bin/gmg addmedia username your_media.jpg + +This will submit the file "your_media.jpg" to be a media entry +associated with the user "username". + +You can get help on all the available options by running:: + + ./bin/gmg addmedia --help + +Here's a longer example that makes use of more options:: + + ./bin/gmg addmedia aveyah awesome_spaceship.png \ + --title "My awesome spaceship" \ + --description "Flying my awesome spaceship, since I'm an awesome pilot" \ + --license "http://creativecommons.org/licenses/by-sa/3.0/" \ + --tags "spaceships, pilots, awesome" \ + --slug "awesome-spaceship" + +You can also pass in the `--celery` option if you would prefer that +your media be passed over to celery to be processed rather than be +processed immediately. + diff --git a/docs/source/siteadmin/deploying.rst b/docs/source/siteadmin/deploying.rst index 77e60037..de4ce1ac 100644 --- a/docs/source/siteadmin/deploying.rst +++ b/docs/source/siteadmin/deploying.rst @@ -1,6 +1,6 @@ .. MediaGoblin Documentation - Written in 2011, 2012 by MediaGoblin contributors + Written in 2011, 2012, 2013 by MediaGoblin contributors To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to @@ -77,7 +77,7 @@ Configure PostgreSQL If you don't want/need postgres, skip this section. -These are the packages needed for Debian Wheezy (testing):: +These are the packages needed for Debian Wheezy (stable):: sudo apt-get install postgresql postgresql-client python-psycopg2 @@ -121,25 +121,62 @@ where the first ``mediagoblin`` is the database owner and the second Drop Privileges for MediaGoblin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -As MediaGoblin does not require special permissions or elevated -access, you should run MediaGoblin under an existing non-root user or -preferably create a dedicated user for the purpose of running -MediaGoblin. Consult your distribution's documentation on how to -create "system account" or dedicated service user. Ensure that it is -not possible to log in to your system with as this user. +MediaGoblin does not require special permissions or elevated +access to run. As such, the prefered way to run MediaGoblin is to +create a dedicated, unpriviledged system user for sole the purpose of running +MediaGoblin. Running MediaGoblin processes under an unpriviledged system user +helps to keep it more secure. + +The following command (entered as root or with sudo) will create a +system account with a username of ``mediagoblin``. You may choose a different +username if you wish.:: + + adduser --system mediagoblin + +No password will be assigned to this account, and you will not be able +to log in as this user. To switch to this account, enter either:: + + sudo su - mediagoblin (if you have sudo permissions) + +or:: + + su - mediagoblin (if you have to use root permissions) + +You may get a warning similar to this when entering these commands:: + + warning: cannot change directory to /home/mediagoblin: No such file or directory + +You can disregard this warning. To return to your regular user account after +using the system account, just enter ``exit``. + +.. note:: + + Unless otherwise noted, the remainder of this document assumes that all + operations are performed using this unpriviledged account. + +.. _create-mediagoblin-directory: + +Create a MediaGoblin Directory +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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. +``/srv/mediagoblin.example.org/mediagoblin/``. +Substitute your prefered local deployment path as needed. + +Setting up the working directory requires that we first create the directory +with elevated priviledges, and then assign ownership of the directory +to the unpriviledged system account. + +To do this, enter either of the following commands, changing the defaults +to suit your particular requirements:: -This document assumes that all operations are performed as this -user. To drop privileges to this user, run the following command:: + sudo mkdir -p /srv/mediagoblin.example.org && sudo chown -hR mediagoblin:mediagoblin /srv/mediagobin.example.org - su - [mediagoblin] +or (as the root user):: + + mkdir -p /srv/mediagoblin.example.org && chown -hR mediagoblin:mediagoblin /srv/mediagobin.example.org -Where, "``[mediagoblin]``" is the username of the system user that will -run MediaGoblin. Install MediaGoblin and Virtualenv ---------------------------------- @@ -151,23 +188,40 @@ Install MediaGoblin and Virtualenv 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:: +We will now clone the MediaGoblin source code repository and setup and +configure the necessary services. Modify these commands to +suit your own environment. As a reminder, you should enter these +commands using your unpriviledged system account. + +Change to the MediaGoblin directory that you just created:: - mkdir -p /srv/mediagoblin.example.org/ - cd /srv/mediagoblin.example.org/ + cd /srv/mediagoblin.example.org -Clone the MediaGoblin repository:: +Clone the MediaGoblin repository and set up the git submodules:: git clone git://gitorious.org/mediagoblin/mediagoblin.git + cd mediagoblin + git submodule init && git submodule update + And set up the in-package virtualenv:: - cd mediagoblin (virtualenv --system-site-packages . || virtualenv .) && ./bin/python setup.py develop .. note:: + We presently have an experimental make-style deployment system. if + you'd like to try it, instead of the above command, you can run:: + + ./bootstrap.sh && ./configure && make + + This also includes a number of nice features, such as keeping your + viratualenv up to date by simply running `make update`. + +.. :: + + (NOTE: Is this still relevant?) + If you have problems here, consider trying to install virtualenv with the ``--distribute`` or ``--no-site-packages`` options. If your system's default Python is in the 3.x series you may need to @@ -194,7 +248,7 @@ This concludes the initial configuration of the development environment. In the future, when you update your codebase, you should also run:: - ./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate + ./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate && git submodule fetch Note: If you are running an active site, depending on your server configuration, you may need to stop it first or the dbupdate command @@ -205,6 +259,23 @@ update) Deploy MediaGoblin Services --------------------------- +Edit site configuration +~~~~~~~~~~~~~~~~~~~~~~~ + +A few basic properties must be set before MediaGoblin will work. First +make a copy of ``mediagoblin.ini`` for editing so the original config +file isn't lost:: + + cp mediagoblin.ini mediagoblin_local.ini + +Then: + - Set ``email_sender_address`` to the address you wish to be used as + the sender for system-generated emails + - Edit ``direct_remote_path``, ``base_dir``, and ``base_url`` if + your mediagoblin directory is not the root directory of your + vhost. + + Configure MediaGoblin to use the PostgreSQL database ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -240,11 +311,11 @@ browser to confirm that the service is operable. .. _webserver-config: -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 and nginx +~~~~~~~~~~~~~~~~~ + +This 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 @@ -310,6 +381,11 @@ this ``nginx.conf`` file should be modeled on the following:: alias /srv/mediagoblin.example.org/mediagoblin/user_dev/theme_static/; } + # Plugin static files (usually symlinked in) + location /plugin_static/ { + alias /srv/mediagoblin.example.org/mediagoblin/user_dev/plugin_static/; + } + # Mounting MediaGoblin itself via FastCGI. location / { fastcgi_pass 127.0.0.1:26543; @@ -345,3 +421,25 @@ Visit the site you've set up in your browser by visiting smaller deployments. However, for larger production deployments with larger processing requirements, see the ":doc:`production-deployments`" documentation. + + +Apache +~~~~~~ + +Instructions and scripts for running MediaGoblin on an Apache server +can be found on the `MediaGoblin wiki <http://wiki.mediagoblin.org/Deployment>`_. + + +Security Considerations +~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: + + The directory ``user_dev/crypto/`` contains some very + sensitive files. + Especially the ``itsdangeroussecret.bin`` is very important + for session security. Make sure not to leak its contents anywhere. + If the contents gets leaked nevertheless, delete your file + and restart the server, so that it creates a new secret key. + All previous sessions will be invalidated. + diff --git a/docs/source/siteadmin/media-types.rst b/docs/source/siteadmin/media-types.rst index 210094b9..3e8a94e9 100644 --- a/docs/source/siteadmin/media-types.rst +++ b/docs/source/siteadmin/media-types.rst @@ -18,16 +18,18 @@ Media Types ==================== In the future, there will be all sorts of media types you can enable, -but in the meanwhile there are three additional media types: video, audio -and ascii art. +but in the meanwhile there are five additional media types: video, audio, +ascii art, STL/3d models, PDF and Document. First, you should probably read ":doc:`configuration`" to make sure you know how to modify the mediagoblin config file. - Enabling Media Types ==================== +.. note:: + Media types are now plugins + Media types are enabled in your mediagoblin configuration file, typically it is created by copying ``mediagoblin.ini`` to ``mediagoblin_local.ini`` and then applying your changes to ``mediagoblin_local.ini``. If you don't already have a @@ -37,11 +39,13 @@ Most media types have additional dependencies that you will have to install. You will find descriptions on how to satisfy the requirements of each media type on this page. -To enable a media type, edit the ``media_types`` list in your -``mediagoblin_local.ini``. For example, if your system supported image and -video media types, then the list would look like this:: +To enable a media type, add the the media type under the ``[plugins]`` section +in you ``mediagoblin_local.ini``. For example, if your system supported image +and video media types, then it would look like this:: - media_types = mediagoblin.media_types.image, mediagoblin.media_types.video + [plugins] + [[mediagoblin.media_types.image]] + [[mediagoblin.media_types.video]] Note that after enabling new media types, you must run dbupdate like so:: @@ -83,8 +87,8 @@ good/bad/ugly). On Debianoid systems gstreamer0.10-ffmpeg -Add ``mediagoblin.media_types.video`` to the ``media_types`` list in your -``mediagoblin_local.ini`` and restart MediaGoblin. +Add ``[[mediagoblin.media_types.video]]`` under the ``[plugins]`` section in +your ``mediagoblin_local.ini`` and restart MediaGoblin. Run @@ -133,7 +137,7 @@ Then install ``scikits.audiolab`` for the spectrograms:: ./bin/pip install scikits.audiolab -Add ``mediagoblin.media_types.audio`` to the ``media_types`` list in your +Add ``[[mediagoblin.media_types.audio]]`` under the ``[plugins]`` section in your ``mediagoblin_local.ini`` and restart MediaGoblin. Run @@ -158,13 +162,8 @@ library, which is necessary for creating thumbnails of ascii art Next, modify (and possibly copy over from ``mediagoblin.ini``) your -``mediagoblin_local.ini``. In the ``[mediagoblin]`` section, add -``mediagoblin.media_types.ascii`` to the ``media_types`` list. - -For example, if your system supported image and ascii art media types, then -the list would look like this:: - - media_types = mediagoblin.media_types.image, mediagoblin.media_types.ascii +``mediagoblin_local.ini``. In the ``[plugins]`` section, add +``[[mediagoblin.media_types.ascii]]``. Run @@ -184,7 +183,7 @@ your execution path. This feature has been tested with Blender 2.63. It may work on some earlier versions, but that is not guaranteed (and is surely not to work prior to Blender 2.5X). -Add ``mediagoblin.media_types.stl`` to the ``media_types`` list in your +Add ``[[mediagoblin.media_types.stl]]`` under the ``[plugins]`` section in your ``mediagoblin_local.ini`` and restart MediaGoblin. Run @@ -199,8 +198,16 @@ will be able to present them to your wide audience of admirers! PDF and Document ================ -To enable the "PDF and Document" support plugin, you need pdftocairo, pdfinfo, -unoconv with headless support. All executables must be on your execution path. +To enable the "PDF and Document" support plugin, you need: + +1. pdftocairo and pdfinfo for pdf only support. + +2. unoconv with headless support to support converting libreoffice supported + documents as well, such as doc/ppt/xls/odf/odg/odp and more. + For the full list see mediagoblin/media_types/pdf/processing.py, + unoconv_supported. + +All executables must be on your execution path. To install this on Fedora: @@ -208,6 +215,9 @@ To install this on Fedora: sudo yum install -y poppler-utils unoconv libreoffice-headless +Note: You can leave out unoconv and libreoffice-headless if you want only pdf +support. This will result in a much smaller list of dependencies. + pdf.js relies on git submodules, so be sure you have fetched them: .. code-block:: bash @@ -222,7 +232,7 @@ This feature has been tested on Fedora with: It may work on some earlier versions, but that is not guaranteed. -Add ``mediagoblin.media_types.pdf`` to the ``media_types`` list in your +Add ``[[mediagoblin.media_types.pdf]]`` under the ``[plugins]`` section in your ``mediagoblin_local.ini`` and restart MediaGoblin. Run diff --git a/docs/source/siteadmin/production-deployments.rst b/docs/source/siteadmin/production-deployments.rst index 1a32d95e..839d3ce5 100644 --- a/docs/source/siteadmin/production-deployments.rst +++ b/docs/source/siteadmin/production-deployments.rst @@ -22,12 +22,14 @@ MediaGoblin in actual production environments. Consider 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 +The MediaGoblin WSGI application instance you get 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: :: +Use the following command as the basis for such a script: + +.. code-block:: bash CELERY_ALWAYS_EAGER=true \ /srv/mediagoblin.example.org/mediagoblin/bin/paster serve \ @@ -41,7 +43,9 @@ 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: :: +as the basis for your script: + +.. code-block:: bash CELERY_ALWAYS_EAGER=false \ /srv/mediagoblin.example.org/mediagoblin/bin/paster serve \ @@ -52,30 +56,40 @@ as the basis for your script: :: Separate Celery --------------- -While the ``./lazyserver.sh`` configuration provides an efficient way to -start using a MediaGoblin instance, it is not suitable for production -deployments for several reasons: +MediaGoblin uses `Celery`_ to handle heavy and long-running tasks. Celery can +be launched in two ways: + +1. Embedded in the MediaGoblin WSGI application [#f-mediagoblin-wsgi-app]_. + This is the way ``./lazyserver.sh`` does it for you. It's simple as you + only have to run one process. The only bad thing with this is that the + heavy and long-running tasks will run *in* the webserver, keeping the user + waiting each time some heavy lifting is needed as in for example processing + a video. This could lead to problems as an aborted connection will halt any + processing and since most front-end web servers *will* terminate your + connection if it doesn't get any response from the MediaGoblin WSGI + application in a while. + +2. As a separate process communicating with the MediaGoblin WSGI application + via a `broker`_. This offloads the heavy lifting from the MediaGoblin WSGI + application and users will be able to continue to browse the site while the + media is being processed in the background. + +.. _`broker`: http://docs.celeryproject.org/en/latest/getting-started/brokers/ +.. _`celery`: http://www.celeryproject.org/ + -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. +.. [#f-mediagoblin-wsgi-app] The MediaGoblin WSGI application is the part that + of MediaGoblin that processes HTTP requests. -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. +To launch Celery separately from the MediaGoblin WSGI application: -Build an :ref:`init script <init-script>` around the following -command:: +1. Make sure that the ``CELERY_ALWAYS_EAGER`` environment variable is unset or + set to ``false`` when launching the MediaGoblin WSGI application. +2. Start the ``celeryd`` main process with - CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_celery ./bin/celeryd + .. code-block:: bash -Modify your existing MediaGoblin and application init scripts, if -necessary, to prevent them from starting their own ``celeryd`` -processes. + CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_celery ./bin/celeryd .. _sentry: @@ -102,7 +116,7 @@ These are scripts provided by the MediaGoblin community: Debian * `GNU MediaGoblin init scripts - <https://github.com/jwandborg/mediagoblin-init-scripts>`_ + <https://github.com/joar/mediagoblin-init-scripts>`_ by `Joar Wandborg <http://wandborg.se>`_ Arch Linux diff --git a/docs/source/siteadmin/relnotes.rst b/docs/source/siteadmin/relnotes.rst index 6962dc5a..3542bdcb 100644 --- a/docs/source/siteadmin/relnotes.rst +++ b/docs/source/siteadmin/relnotes.rst @@ -11,6 +11,8 @@ Dedication along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. +.. _release-notes: + ============= Release Notes ============= @@ -19,6 +21,250 @@ This chapter has important information for releases in it. If you're upgrading from a previous release, please read it carefully, or at least skim over it. +0.6.1 +===== + +This is a short, bugfix release. + +**Do this to upgrade** + +1. Update to the latest release. If checked out from git, run: + ``git fetch && git checkout -q v0.6.1`` +2. Make sure to run + ``./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate`` + +This release switches the default terms of service to be off by +default and corrects some mistakes in the default terms of service. + +Turning the terms of service on is very easy, just set ``show_tos`` in +the ``[mediagoblin]`` section of your config to ``true``. + + +0.6.0 +===== + +**Do this to upgrade** + +1. Update to the latest release. If checked out from git, run: + ``git fetch && git checkout -q v0.6.0`` +2. Make sure to run + ``./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate`` + +That's it, probably! If you run into problems, don't hesitate to +`contact us <http://mediagoblin.org/pages/join.html>`_ +(IRC is often best). + +This tool has a lot of new tools for administrators, hence the +nickname "Lore of the Admin"! + +**New features:** + +- New tools to control how much users can upload, both as a general + user limit, or per file. + + You can set this with the following options in your mediagoblin + config file: `upload_limit` and `max_file_size`. Both are integers + in megabytes. + + There is an option to control how much each individual user can + upload too, though an interface for this is not yet exposed. See + the "uploaded" field on the core__users table. + +- MediaGoblin now contains an authentication plugin for ldap! You + can turn on the mediagoblin.plugins.ldap plugin to make use of + this. See the documentation: :ref:`ldap-plugin` + +- There's a new command line upload tool! At long last! See + `./bin/gmg addmedia --help` for info on how to use this. + +- There's now a terms of service document included in MediaGoblin. + It's turned on by default, but you can turn it off if you prefer, + just set the configuration option of `show_tos` in the [mediagoblin] + section of your config to false. + + Alternately, you can override the template for the terms of service + document to set up your own. + +- We have a lot of new administrative tooling features! + - There's a built-in privileges/permissions system now. + Administrators are given access to modifying these parameters + from a user administration panel. + - Users can submit reports about other problematic users or media + and administrators are given tools to resolve said reports and + ban/unban users if needed. + +- New version of video.js is included with MediaGoblin. Slight + amount of skinning to match the MediaGoblin look, otherwise also + uses the new default skin. + +Developer-oriented changes: + +- New developer tool for quickly setting up a development environment + in `devtools/make_example_database.sh`. Requires doing a checkout + of our other tool `mg_dev_environments <https://gitorious.org/mediagoblin/mg-dev-environments/>`_ + (probably in the parent Directory) though! +- A "foundations" framework has entered into the codebase. + This is mostly just relevant to coders, but it does mean that it's + much easier to add database structures that need some entries filled + automatically by default. +- Refactoring to the authentication code and the reprocessing code + + +0.5.1 +===== + +v0.5.1 is a bugfix release... the steps are the same as for 0.5.1. + +**Bugfixes:** + +- python 2.6 compatibility restored +- Fixed last release's release notes ;) + + +0.5.0 +===== + +**NOTE:** If using the API is important to you, we're in a state of +ransition towards a new API via the Pump API. As such, though the old +API still probably works, some changes have happened to the way oauth +works to make it more Pump-compatible. If you're heavily using +clients using the old API, you may wish to hold off on upgrading for +now. Otherwise, jump in and have fun! :) + +**Do this to upgrade** + +1. Make sure to run + ``./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate`` + after upgrading. + +.. mention something about new, experimental configure && make support + +2. Note that a couple of things have changed with ``mediagoblin.ini``. First + we have a new Authentication System. You need to add + ``[[mediagoblin.plugins.basic_auth]]`` under the ``[plugins]`` section of + your config file. Second, media types are now plugins, so you need to add + each media type under the ``[plugins]`` section of your config file. + + +3. We have made a script to transition your ``mediagoblin_local.ini`` file for + you. This script can be found at: + + http://mediagoblin.org/download/0.5.0_config_converter.py + +If you run into problems, don't hesitate to +`contact us <http://mediagoblin.org/pages/join.html>`_ +(IRC is often best). + +**New features** + +* As mentioned above, we now have a plugable Authentication system. You can + use any combination of the multiple authentication systems + (:ref:`basic_auth-chapter`, :ref:`persona-chapter`, :ref:`openid-chapter`) + or write your own! +* Media types are now plugins! This means that new media types will + be able to do new, fancy things they couldn't in the future. +* We now have notification support! This allows you to subscribe to media + comments and to be notified when someone comments on your media. +* New reprocessing framework! You can now reprocess failed uploads, and + send already processed media back to processing to re-transcode or resize + media. +* Comment preview! +* Users now have the ability to change their email associated with their + account. +* New oauth code as we move closer to federation support. +* Experimental pyconfigure support for GNU-style configue and makefile + deployment. +* Database foundations! You can now pre-populate the database models. +* Way faster unit test run-time via in-memory database. +* All mongokit stuff has been cleaned up. +* Fixes for non-ascii filenames. +* The option to stay logged in. +* Mediagoblin has been upgraded to use the latest `celery <http://celeryproject.org/>`_ + version. +* You can now add jinja2 extensions to your config file to use in custom + templates. +* Fixed video permission issues. +* Mediagoblin docs are now hosted with multiple versions. +* We removed redundent tooltips from the STL media display. +* We are now using itsdangerous for verification tokens. + + +0.4.1 +===== + +This is a bugfix release for 0.4.0. This only implements one major +fix in the newly released document support which prevented the +"conversion via libreoffice" feature. + +If you were running 0.4.0 you can upgrade to v0.4.1 via a simple +switch and restarting mediagoblin/celery with no other actions. + +Otherwise, follow 0.4.0 instructions. + + +0.4.0 +===== + +**Do this to upgrade** + +1. Make sure to run + ``./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate`` + after upgrading. +2. See "For Theme authors" if you have a custom theme. +3. Note that ``./bin/gmg theme assetlink`` is now just + ``./bin/gmg assetlink`` and covers both plugins and assets. + Keep on reading to hear more about new plugin features. +4. If you want to take advantage of new plugins that have statically + served assets, you are going to need to add the new "plugin_static" + section to your nginx config. Basically the following for nginx:: + + # Plugin static files (usually symlinked in) + location /plugin_static/ { + alias /srv/mediagoblin.example.org/mediagoblin/user_dev/plugin_static/; + } + + Similarly, if you've got a modified paste config, you may want to + borrow the app:plugin_static section from the default paste.ini + file. +5. We now use itsdangerous for sessions; if you had any references to + beaker in your paste config you can remove them. Again, see the + default paste.ini config +6. We also now use git submodules. Please do: + ``git submodule init && git submodule update`` + You will need to do this to use the new PDF support. + +**For theme authors** + +If you have your own theme or you have any "user modified templates", +please note the following: + +* mediagoblin/bits/ files above-content.html, body-end.html, + body-start.html now are renamed... they have underscores instead of + dashes in the filenames now :) +* There's a new file: ``mediagoblin/bits/frontpage_welcome.html``. + You can easily customize this to give a welcome page appropriate to + your site. + + +**New features** + +* PDF media type! +* Improved plugin system. More flexible, better documented, with a + new plugin authoring section of the docs. +* itsdangerous based sessions. No more beaker! +* New, experimental Piwigo-based API. This means you should be able + to use MediaGoblin with something like Shotwell. (Again, a word of + caution: this is *very experimental*!) +* Human readable timestamps, and the option to display the original + date of an image when available (available as the + "original_date_visible" variable) +* Moved unit testing system from nosetests to py.test so we can better + handle issues with sqlalchemy exploding with different database + configurations. Long story :) +* You can now disable the ability to post comments. +* Tags now can be up to length 255 characters by default. + + 0.3.3 ===== @@ -30,8 +276,8 @@ carefully, or at least skim over it. .. code-block:: ini - [plugins] - [[mediagoblin.plugins.geolocation]] + [plugins] + [[mediagoblin.plugins.geolocation]] If you have your own theme, you may need to make some adjustments to it as some theme related things may have changed in this release. If @@ -100,7 +346,19 @@ MongoDB-based MediaGoblin instance to the newer SQL-based system. **Do this to upgrade** -1. Make sure to run ``bin/gmg dbupdate`` after upgrading. + # directory of your mediagoblin install + cd /srv/mediagoblin.example.org + + # copy source for this release + git fetch + git checkout tags/v0.3.2 + + # perform any needed database updates + bin/gmg dbupdate + + # restart your servers however you do that, e.g., + sudo service mediagoblin-paster restart + sudo service mediagoblin-celeryd restart **New features** diff --git a/docs/source/siteadmin/theming.rst b/docs/source/siteadmin/theming.rst index 98ec6de7..11ae3875 100644 --- a/docs/source/siteadmin/theming.rst +++ b/docs/source/siteadmin/theming.rst @@ -51,7 +51,7 @@ want to install this theme! Don't worry, it's fairly painless. 5. Link the assets so that they can be served by your web server:: - $ ./bin/gmg theme assetlink + $ ./bin/gmg assetlink .. Note:: diff --git a/extlib/tinymce/LICENSE.TXT b/extlib/tinymce/LICENSE.TXT new file mode 100644 index 00000000..1837b0ac --- /dev/null +++ b/extlib/tinymce/LICENSE.TXT @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/extlib/tinymce/changelog.txt b/extlib/tinymce/changelog.txt new file mode 100644 index 00000000..165205b7 --- /dev/null +++ b/extlib/tinymce/changelog.txt @@ -0,0 +1,157 @@ +Version 4.0.2 (2013-07-18) + Fixed bug where formatting using menus or toolbars wasn't possible on Opera 12.15. + Fixed bug where IE 8 keyboard input would break after paste using the paste plugin. + Fixed bug where IE 8 would throw an error when populating image size in image dialog. + Fixed bug where image resizing wouldn't work properly on latest IE 10.0.9 version. + Fixed bug where focus wasn't moved to the hovered menu button in a menubar container. + Fixed bug where paste would produce an extra uneeded undo level on IE and Gecko. + Fixed so anchors gets listed in the link dialog as they where in TinyMCE 3.x. + Fixed so sub, sup and strike though gets passed through when pasting from Word. + Fixed so Ctrl+P can be used to print the current document. Patch contributed by jashua212. +Version 4.0.1 (2013-06-26) + Added new paste_as_text config option to force paste as plaintext mode. + Added new pastetext menu item that lets you toggle paste as plain text mode on/off. + Added new insertdatetime_element option to insertdatetime plugin. Enables HTML5 time element support. + Added new spellchecker_wordchar_pattern option to allow configuration of language specific characters. + Added new marker to formats menu displaying the formats used at the current selection/caret location. + Fixed bug where the position of the text color picker would be wrong if you switched to fullscreen. + Fixed bug where the link plugin would ask to add the mailto: prefix multiple times. + Fixed bug where list outdent operation could produce empty list elements on specific selections. + Fixed bug where element path wouldn't properly select parent elements on IE. + Fixed bug where IE would sometimes throw an exception when extrancting the current selection range. + Fixed bug where line feeds wasn't properly rendered in source view on IE. + Fixed bug where word count wouldn't be properly rendered on IE 7. + Fixed bug where menubuttons/listboxes would have an incorrect height on IE 7. + Fixed bug where browser spellchecking was enabled while editing inline on IE 10. + Fixed bug where spellchecker wouldn't properly find non English words. + Fixed bug where deactivating inline editor instances would force padding-top: 0 on page body. + Fixed bug where jQuery would initialize editors multiple times since it didn't check if the editor already existed. + Fixed bug where it wasn't possible to paste contents on IE 10 in modern UI mode when paste filtering was enabled. + Fixed bug where tabfocus plugin wouldn't work properly on inline editor instances. + Fixed bug where fullpage plugin would clear the existing HTML head if contents where inserted into the editor. + Fixed bug where deleting all table rows/columns in a table would cause an exception to be thrown on IE. + Fixed so color button panels gets toggled on/off when activated/deactivated. + Fixed so format menu items that can't be applied to the current selection gets disabled. + Fixed so the icon parameter for addButton isn't automatically filled if a button text is provided. + Fixed so image size fields gets updated when selecting a new image in the image dialog. + Fixed so it doesn't load any language pack if the language option is set to "en". + Fixed so ctrl+shift+z works as an alternative redo shortcut to match a common Mac OS X shortcut. + Fixed so it's not possible to drag/drop in images in Gecko by default when paste plugin is enabled. + Fixed so format menu item texts gets translated using the specified language pack. + Fixed so the image dialog title is the same as the insert/edit image button text. + Fixed so paste as plain text produces BR:s in PRE block and when forced_root_block is disabled. +Version 4.0 (2013-06-13) + Added new insertdate_dateformat, insertdate_timeformat and insertdate_formats options to insertdatetime. + Added new font_formats, fontsize_formats and block_formats options to configure fontselect, fontsizeselect and formatselect. + Added new table_clone_elements option to table plugin. Enables you to specify what elements to clone when adding columns/rows. + Added new auto detect logic for site and email urls in link plugin to match the logic found in 3.x. + Added new getParams/setParams to WindowManager to make it easier to handle params to iframe based dialogs. Contributed by Ryan Demmer. + Added new textcolor options that enables you to specify the colors you want to display. Contributed by Jennifer Arsenault. + Added new external file support for link_list and image_list options. The file format is a simple JSON file. + Added new "both" mode for the resize option. Enables resizing in both width and height. + Added new paste_data_images option that allows you to enable/disable paste of data images. + Added new fixed_toolbar_container option that allows you to add a fixed container for the inline toolbar. + Fixed so font name, font size and block format select boxes gets updated with the current format. + Fixed so the resizeTo/resizeBy methods for the theme are exposed as it as in 3.x. + Fixed so the textcolor controls are splitbuttons as in 3.x. Patch contributed by toxalot/jashua212. + Fixed bug where the theme content css wasn't loaded into the preview dialog. + Fixed bug where the template description in template dialog wouldn't display the text correctly. + Fixed bug where various UI elements wasn't properly removed when an editor instance was removed. + Fixed bug where editing links in inline mode would fail on WebKit. + Fixed bug where the pagebreak_separator option in the pagebreak plugin wasn't working properly. + Fixed bug where the child panels of the float panel in inline mode wasn't properly placed. + Fixed bug where the float panel children of windows wasn't position fixed. + Fixed bug where the size of the ok button was hardcoded, caused issues with i18n. + Fixed bug where single comment in editor would cause exceptions due to resolve path logic not detecting elements only. + Fixed bug where switching alignment of tables in dialogs wouldn't properly remove existing alignments. + Fixed bug where the table properties dialog would show columns/rows textboxes. + Fixed bug where jQuery wasn't used instead of Sizzle in the jQuery version of TinyMCE. + Fixed bug where setting resize option to false whouldn't properly render the word count. + Fixed bug where table row type change would produce multiple table section elements. + Fixed bug where table row type change on multiple rows would add them in incorrect order. + Fixed bug where fullscreen plugin would maximize the editor on resize after toggling it off. + Fixed bug where context menu would be position at an incorrect coordinate in inline mode. + Fixed bug where inserting lists in inline mode on IE would produce errors since the body would be converted. + Fixed bug where the body couldn't be styled properly in custom content_css files. + Fixed bug where template plugins menu item would override the image menu item. + Fixed bug where IE 7-8 would render the text inside inputs at the wrong vertical location. + Fixed bug where IE configured to IE 7 compatibility mode wouldn't render the icons properly. + Fixed bug where editor.focus wouldn't properly fire the focusin event on WebKit. + Fixed bug where some keyboard shortcuts wouldn't work on IE 8. + Fixed bug where the undo state wasn't updated until the end of a typing level. + Fixed bug where keyboard shortcuts on Mac OS wasn't working correctly. + Fixed bug where empty inline elements would be created when toggling formatting of in empty block. + Fixed bug where applying styles on WebKit would fail in inline mode if the user released the mouse button outside the body. + Fixed bug where the visual aids menu item wasn't selected if the editor was empty. + Fixed so the isDirty/isNotDirty states gets updated to true/false on save() and change events. + Fixed so skins have separate CSS files for inline and iframe mode. + Fixed so menus and tool tips gets constrained to the current viewport. + Fixed so an error is thrown if users load jQuery after the jQuery version of TinyMCE. + Fixed so the filetype for media dialog passes out media instead of image as file type. + Fixed so it's possible to disable the toolbar by setting it to false. + Fixed so autoresize plugin isn't initialized when the editor is in inline mode. + Fixed so the inline editing toolbar will be rendered below elements if it doesn't fit above it. +Version 4.0b3 (2013-05-15) + Added new optional advanced tab for image dialog with hspace, vspace, border and style. + Added new change event that gets fired when undo levels are added to editor instances. + Added new removed_menuitems option enables you to list menu items to remove from menus. + Added new external_plugins option enables you to specify external locations for plugins. + Added new language_url option enables you to specify an external location for the language pack. + Added new table toolbar control that displays a menu for inserting/editing menus. + Fixed bug where IE 10 wouldn't load files properly from cache. + Fixed bug where image dialog wouldn't properly remove width/height if blanked. + Fixed bug where all events wasn't properly unbound when editor instances where removed. + Fixed bug where data- attributes wasn't working properly in the SaxParser. + Fixed bug where Gecko wouldn't properly render broken images. + Fixed bug where Gecko wouldn't produce the same error dialog on paste as other browsers. + Fixed bug where is wasn't possible to prevent execCommands in beforeExecCommand event. + Fixed bug where the fullpage_hide_in_source_view option wasn't working in the fullpage plugin. + Fixed bug where the WindowManager close method wouldn't properly close the top most window. + Fixed bug where it wasn't possible to paste in IE 10 due to JS exception. + Fixed bug where tab key didn't move to the right child control in tabpanels. + Fixed bug where enter inside a form would focus the first button like control in TinyMCE. + Fixed bug where it would match scripts that looked like the tinymce base directory incorrectly. + Fixed bug where the spellchecker wouldn't properly toggle off the spellcheck mode if no errors where found. + Fixed bug in searchreplace plugin where it would remove all spans instead of the marker spans. + Fixed issue where selector wouldn't disable existing mode setting. + Fixed so it's easier to configure the menu and menubar. + Fixed so bodyId/bodyClass is applied to preview as it's done to the editor iframe. +Version 4.0b2 (2013-04-24) + Added new rel_list option to link plugin. Enables you to specify values for a rel drop down. + Added new target_list option to link plugin. Enables you to add to or disable the link targets. + Added new link_list option to link plugin. Enables you to specify a list of links to pick from. + Added new image_list option to image pluigin. Enables you to specify a list of images to pick from. + Added new textcolor plugin. This plugin holds the text color and text background color buttons. + Fixed bug where alignment of images wasn't working properly on Firefox. + Fixed bug where IE 8 would throw error when inserting a table. + Fixed bug where IE 8 wouldn't render the element path properly. + Fixed bug where old IE versions would render a red focus border. + Fixed bug where old IE versions would render a frameborder for iframes. + Fixed bug where WebKit wouldn't properly open the cell properties dialog on edge case selection. + Fixed bug where charmap wouldn't correctly render all characters in grid. + Fixed bug where link dialog wouldn't update the link text properly. + Fixed bug where the focus/blur states on inline editors wasn't handled correctly on IE. + Fixed bug where IE would throw "unknown error" exception sometimes in ForceBlocks logic. + Fixed bug where IE would't properly render disabled buttons in button groups. + Fixed bug where tab key wouldn't properly move to next input field in dialogs. + Fixed bug where resize handles for tables and images would appear at wrong positions on IE 8. + Fixed bug where dialogs would produce stack overflow if title was wider than content. + Fixed bug with table cell/row menu items being enabled even if no cell was selected. + Fixed so the text to display is after the URL field in the link dialog. + Fixed so the width setting applies to the editor panel in modern theme. + Fixed so it's easier to make custom icons for buttons using plain old images. +Version 4.0b1 (2013-04-11) + Added new node.js based build process used uglify, amdlc, jake etc. + Added new package.json to enable easy installation of dependent npm packages used for building. + Added new link, image, charmap, anchor, code, hr plugins since these are now moved out of the theme. + Rewrote all plugins and themes from scratch so they match the new UI framework. + Replaced all events to use the more common <target>.on/off(<event>) methods instead of <target>.<event>.add/remove. + Rewrote the TinyMCE core to use AMD style modules. Gets compiled to an inline library using amdlc. + Rewrote all core logic to pass jshint rules. Each file has specific jshint rules. + Removed all IE6 specific logic since 4.x will no longer support such an old browser. + Reworked the file names and directory structure of the whole project to be more similar to other JS projects. + Replaced tinymce.util.Cookie with tinymce.util.LocalStorage. Fallback to userData for IE 7 native localStorage for the rest. + Replaced the old 3.x UI with a new modern UI framework. + Removed "simple" theme and added new "modern" theme. + Removed advhr, advimage, advlink, iespell, inlinepopups, xhtmlxtras and style plugins. + Updated Sizzle to the latest version. diff --git a/extlib/tinymce/js/tinymce/langs/readme.md b/extlib/tinymce/js/tinymce/langs/readme.md new file mode 100644 index 00000000..a52bf03f --- /dev/null +++ b/extlib/tinymce/js/tinymce/langs/readme.md @@ -0,0 +1,3 @@ +This is where language files should be placed. + +Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/ diff --git a/extlib/tinymce/js/tinymce/license.txt b/extlib/tinymce/js/tinymce/license.txt new file mode 100644 index 00000000..1837b0ac --- /dev/null +++ b/extlib/tinymce/js/tinymce/license.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/extlib/tinymce/js/tinymce/plugins/advlist/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/advlist/plugin.min.js new file mode 100644 index 00000000..da1cdb2b --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/advlist/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("advlist",function(t){function e(t,e){var n=[];return tinymce.each(e.split(/[ ,]/),function(t){n.push({text:t.replace(/\-/g," ").replace(/\b\w/g,function(t){return t.toUpperCase()}),data:"default"==t?"":t})}),n}function n(e,n){var i,r=t.dom,a=t.selection;i=r.getParent(a.getNode(),"ol,ul"),i&&i.nodeName==e&&n!==!1||t.execCommand("UL"==e?"InsertUnorderedList":"InsertOrderedList"),n=n===!1?o[e]:n,o[e]=n,i=r.getParent(a.getNode(),"ol,ul"),i&&(r.setStyle(i,"listStyleType",n),i.removeAttribute("data-mce-style")),t.focus()}function i(e){var n=t.dom.getStyle(t.dom.getParent(t.selection.getNode(),"ol,ul"),"listStyleType")||"";e.control.items().each(function(t){t.active(t.settings.data===n)})}var r,a,o={};r=e("OL",t.getParam("advlist_number_styles","default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman")),a=e("UL",t.getParam("advlist_bullet_styles","default,circle,disc,square")),t.addButton("numlist",{type:"splitbutton",tooltip:"Numbered list",menu:r,onshow:i,onselect:function(t){n("OL",t.control.settings.data)},onclick:function(){n("OL",!1)}}),t.addButton("bullist",{type:"splitbutton",tooltip:"Bullet list",menu:a,onshow:i,onselect:function(t){n("UL",t.control.settings.data)},onclick:function(){n("UL",!1)}})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/anchor/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/anchor/plugin.min.js new file mode 100644 index 00000000..058e686e --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/anchor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("anchor",function(n){function e(){var e=n.selection.getNode();n.windowManager.open({title:"Anchor",body:{type:"textbox",name:"name",size:40,label:"Name",value:e.name||e.id},onsubmit:function(e){n.execCommand("mceInsertContent",!1,n.dom.createHTML("a",{id:e.data.name}))}})}n.addButton("anchor",{icon:"anchor",tooltip:"Anchor",onclick:e,stateSelector:"a:not([href])"}),n.addMenuItem("anchor",{icon:"anchor",text:"Anchor",context:"insert",onclick:e})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/autolink/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/autolink/plugin.min.js new file mode 100644 index 00000000..3d2f58ee --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/autolink/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autolink",function(t){function e(t){o(t,-1,"(",!0)}function n(t){o(t,0,"",!0)}function i(t){o(t,-1,"",!1)}function o(t,e,n){var i,o,r,a,s,l,c,u,d;if(i=t.selection.getRng(!0).cloneRange(),i.startOffset<5){if(u=i.endContainer.previousSibling,!u){if(!i.endContainer.firstChild||!i.endContainer.firstChild.nextSibling)return;u=i.endContainer.firstChild.nextSibling}if(d=u.length,i.setStart(u,d),i.setEnd(u,d),i.endOffset<5)return;o=i.endOffset,a=u}else{if(a=i.endContainer,3!=a.nodeType&&a.firstChild){for(;3!=a.nodeType&&a.firstChild;)a=a.firstChild;3==a.nodeType&&(i.setStart(a,0),i.setEnd(a,a.nodeValue.length))}o=1==i.endOffset?2:i.endOffset-1-e}r=o;do i.setStart(a,o>=2?o-2:0),i.setEnd(a,o>=1?o-1:0),o-=1;while(" "!=i.toString()&&""!==i.toString()&&160!=i.toString().charCodeAt(0)&&o-2>=0&&i.toString()!=n);if(i.toString()==n||160==i.toString().charCodeAt(0)?(i.setStart(a,o),i.setEnd(a,r),o+=1):0===i.startOffset?(i.setStart(a,0),i.setEnd(a,r)):(i.setStart(a,o),i.setEnd(a,r)),l=i.toString(),"."==l.charAt(l.length-1)&&i.setEnd(a,r-1),l=i.toString(),c=l.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i),c&&("www."==c[1]?c[1]="http://www.":/@$/.test(c[1])&&!/^mailto:/.test(c[1])&&(c[1]="mailto:"+c[1]),s=t.selection.getBookmark(),t.selection.setRng(i),t.execCommand("createlink",!1,c[1]+c[2]),t.selection.moveToBookmark(s),t.nodeChanged(),tinymce.Env.webkit)){t.selection.collapse(!1);var m=Math.min(a.length,r+1);i.setStart(a,m),i.setEnd(a,m),t.selection.setRng(i)}}t.on("keydown",function(e){return 13==e.keyCode?i(t):void 0}),tinymce.Env.ie||(t.on("keypress",function(n){return 41==n.which?e(t):void 0}),t.on("keyup",function(e){return 32==e.keyCode?n(t):void 0}))});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/autoresize/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/autoresize/plugin.min.js new file mode 100644 index 00000000..12355aa9 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/autoresize/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autoresize",function(e){function t(a){var r,o,c=e.getDoc(),s=c.body,u=c.documentElement,l=tinymce.DOM,m=n.autoresize_min_height;"setcontent"==a.type&&a.initial||e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen()||(o=tinymce.Env.ie?s.scrollHeight:tinymce.Env.webkit&&0===s.clientHeight?0:s.offsetHeight,o>n.autoresize_min_height&&(m=o),n.autoresize_max_height&&o>n.autoresize_max_height?(m=n.autoresize_max_height,s.style.overflowY="auto",u.style.overflowY="auto"):(s.style.overflowY="hidden",u.style.overflowY="hidden",s.scrollTop=0),m!==i&&(r=m-i,l.setStyle(l.get(e.id+"_ifr"),"height",m+"px"),i=m,tinymce.isWebKit&&0>r&&t(a)))}var n=e.settings,i=0;e.settings.inline||(n.autoresize_min_height=parseInt(e.getParam("autoresize_min_height",e.getElement().offsetHeight),10),n.autoresize_max_height=parseInt(e.getParam("autoresize_max_height",0),10),e.on("init",function(){e.dom.setStyle(e.getBody(),"paddingBottom",e.getParam("autoresize_bottom_margin",50)+"px")}),e.on("change setcontent paste keyup",t),e.getParam("autoresize_on_init",!0)&&e.on("load",t),e.addCommand("mceAutoResize",t))});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/autosave/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/autosave/plugin.min.js new file mode 100644 index 00000000..31a46d7f --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/autosave/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autosave",function(t){function e(t,e){var n={s:1e3,m:6e4};return t=/^(\d+)([ms]?)$/.exec(""+(t||e)),(t[2]?n[t[2]]:1)*parseInt(t,10)}function n(){var t=parseInt(m.getItem(f+"autosave.time"),10)||0;return(new Date).getTime()-t>d.autosave_retention?(i(),!1):!0}function i(){m.removeItem(f+"autosave.draft"),m.removeItem(f+"autosave.time")}function a(){c&&t.isDirty()&&(m.setItem(f+"autosave.draft",t.getContent({format:"raw",no_events:!0})),m.setItem(f+"autosave.time",(new Date).getTime()),t.fire("StoreDraft"))}function r(){n()&&(t.setContent(m.getItem(f+"autosave.draft"),{format:"raw"}),i(),t.fire("RestoreDraft"))}function o(){c||(setInterval(function(){t.removed||a()},d.autosave_interval),c=!0)}function s(){var e=this;e.disabled(!n()),t.on("StoreDraft RestoreDraft",function(){e.disabled(!n())}),o()}function l(){t.undoManager.beforeChange(),r(),t.undoManager.add()}function u(){var t;return tinymce.each(tinymce.editors,function(e){e.plugins.autosave&&e.plugins.autosave.storeDraft(),!t&&e.isDirty()&&e.getParam("autosave_ask_before_unload",!0)&&(t=e.translate("You have unsaved changes are you sure you want to navigate away?"))}),t}var c,d=t.settings,m=tinymce.util.LocalStorage,f=t.id;d.autosave_interval=e(d.autosave_interval,"30s"),d.autosave_retention=e(d.autosave_retention,"20m"),t.addButton("restoredraft",{title:"Restore last draft",onclick:l,onPostRender:s}),t.addMenuItem("restoredraft",{text:"Restore last draft",onclick:l,onPostRender:s,context:"file"}),this.storeDraft=a,window.onbeforeunload=u});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/bbcode/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/bbcode/plugin.min.js new file mode 100644 index 00000000..70a88a7d --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/bbcode/plugin.min.js @@ -0,0 +1 @@ +!function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(e){var t=this,n=e.getParam("bbcode_dialect","punbb").toLowerCase();e.on("beforeSetContent",function(e){e.content=t["_"+n+"_bbcode2html"](e.content)}),e.on("postProcess",function(e){e.set&&(e.content=t["_"+n+"_bbcode2html"](e.content)),e.get&&(e.content=t["_"+n+"_html2bbcode"](e.content))})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://www.tinymce.com",infourl:"http://www.tinymce.com/wiki.php/Plugin:bbcode"}},_punbb_html2bbcode:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"),t(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"),t(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]"),t(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"),t(/<font>(.*?)<\/font>/gi,"$1"),t(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"),t(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]"),t(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]"),t(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),t(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),t(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),t(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),t(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),t(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),t(/<\/(strong|b)>/gi,"[/b]"),t(/<(strong|b)>/gi,"[b]"),t(/<\/(em|i)>/gi,"[/i]"),t(/<(em|i)>/gi,"[i]"),t(/<\/u>/gi,"[/u]"),t(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"),t(/<u>/gi,"[u]"),t(/<blockquote[^>]*>/gi,"[quote]"),t(/<\/blockquote>/gi,"[/quote]"),t(/<br \/>/gi,"\n"),t(/<br\/>/gi,"\n"),t(/<br>/gi,"\n"),t(/<p>/gi,""),t(/<\/p>/gi,"\n"),t(/ |\u00a0/gi," "),t(/"/gi,'"'),t(/</gi,"<"),t(/>/gi,">"),t(/&/gi,"&"),e},_punbb_bbcode2html:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/\n/gi,"<br />"),t(/\[b\]/gi,"<strong>"),t(/\[\/b\]/gi,"</strong>"),t(/\[i\]/gi,"<em>"),t(/\[\/i\]/gi,"</em>"),t(/\[u\]/gi,"<u>"),t(/\[\/u\]/gi,"</u>"),t(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'<a href="$1">$2</a>'),t(/\[url\](.*?)\[\/url\]/gi,'<a href="$1">$1</a>'),t(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />'),t(/\[color=(.*?)\](.*?)\[\/color\]/gi,'<font color="$1">$2</font>'),t(/\[code\](.*?)\[\/code\]/gi,'<span class="codeStyle">$1</span> '),t(/\[quote.*?\](.*?)\[\/quote\]/gi,'<span class="quoteStyle">$1</span> '),e}}),tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)}();
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/charmap/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/charmap/plugin.min.js new file mode 100644 index 00000000..dff18e6e --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/charmap/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("charmap",function(e){function t(){function t(e){for(;e;){if("TD"==e.nodeName)return e;e=e.parentNode}}var i,a,r,o;i='<table role="presentation" cellspacing="0" class="mce-charmap"><tbody>';var s=25;for(r=0;10>r;r++){for(i+="<tr>",a=0;s>a;a++){var l=n[r*s+a],c="g"+(r*s+a);i+='<td title="'+l[1]+'"><div id="'+c+'" tabIndex="-1">'+(l?String.fromCharCode(parseInt(l[0],10)):" ")+"</div></td>"}i+="</tr>"}i+="</tbody></table>";var u={type:"container",html:i,onclick:function(t){var n=t.target;"DIV"==n.nodeName&&e.execCommand("mceInsertContent",!1,n.firstChild.nodeValue)},onmouseover:function(e){var n=t(e.target);n&&o.find("#preview").text(n.firstChild.firstChild.data)}};o=e.windowManager.open({title:"Special character",spacing:10,padding:10,items:[u,{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:100,minHeight:80}],buttons:[{text:"Close",onclick:function(){o.close()}}]})}var n=[["160","no-break space"],["38","ampersand"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","seconds / inches"],["167","section sign"],["182","paragraph sign"],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en dash"],["8212","em dash"],["175","macron"],["8254","overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three quarters"],["402","function / florin"],["8747","integral"],["8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["8709","diameter"],["8711","backward difference"],["8727","asterisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"],["203","E - diaeresis"],["204","I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["221","Y - acute"],["376","Y - diaeresis"],["222","THORN"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["240","eth"],["241","n - tilde"],["242","o - grave"],["243","o - acute"],["244","o - circumflex"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920","Theta"],["921","Iota"],["922","Kappa"],["923","Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu"],["957","nu"],["958","xi"],["959","omicron"],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629","carriage return"],["8656","leftwards double arrow"],["8657","upwards double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["9002","right-pointing angle bracket"],["9674","lozenge"],["9824","black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"],["173","soft hyphen"]];e.addButton("charmap",{icon:"charmap",tooltip:"Special character",onclick:t}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",onclick:t,context:"insert"})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/code/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/code/plugin.min.js new file mode 100644 index 00000000..30736376 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/code/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("code",function(e){function t(){e.windowManager.open({title:"Source code",body:{type:"textbox",name:"code",multiline:!0,minWidth:600,minHeight:500,value:e.getContent({source_view:!0}),spellcheck:!1},onSubmit:function(t){e.setContent(t.data.code)}})}e.addButton("code",{icon:"code",tooltip:"Source code",onclick:t}),e.addMenuItem("code",{icon:"code",text:"Source code",context:"tools",onclick:t})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/compat3x/editable_selects.js b/extlib/tinymce/js/tinymce/plugins/compat3x/editable_selects.js new file mode 100644 index 00000000..8d30787d --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/compat3x/editable_selects.js @@ -0,0 +1,70 @@ +/** + * editable_selects.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +var TinyMCE_EditableSelects = { + editSelectElm : null, + + init : function() { + var nl = document.getElementsByTagName("select"), i, d = document, o; + + for (i=0; i<nl.length; i++) { + if (nl[i].className.indexOf('mceEditableSelect') != -1) { + o = new Option(tinyMCEPopup.editor.translate('value'), '__mce_add_custom__'); + + o.className = 'mceAddSelectValue'; + + nl[i].options[nl[i].options.length] = o; + nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect; + } + } + }, + + onChangeEditableSelect : function(e) { + var d = document, ne, se = window.event ? window.event.srcElement : e.target; + + if (se.options[se.selectedIndex].value == '__mce_add_custom__') { + ne = d.createElement("input"); + ne.id = se.id + "_custom"; + ne.name = se.name + "_custom"; + ne.type = "text"; + + ne.style.width = se.offsetWidth + 'px'; + se.parentNode.insertBefore(ne, se); + se.style.display = 'none'; + ne.focus(); + ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput; + ne.onkeydown = TinyMCE_EditableSelects.onKeyDown; + TinyMCE_EditableSelects.editSelectElm = se; + } + }, + + onBlurEditableSelectInput : function() { + var se = TinyMCE_EditableSelects.editSelectElm; + + if (se) { + if (se.previousSibling.value != '') { + addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value); + selectByValue(document.forms[0], se.id, se.previousSibling.value); + } else + selectByValue(document.forms[0], se.id, ''); + + se.style.display = 'inline'; + se.parentNode.removeChild(se.previousSibling); + TinyMCE_EditableSelects.editSelectElm = null; + } + }, + + onKeyDown : function(e) { + e = e || window.event; + + if (e.keyCode == 13) + TinyMCE_EditableSelects.onBlurEditableSelectInput(); + } +}; diff --git a/extlib/tinymce/js/tinymce/plugins/compat3x/form_utils.js b/extlib/tinymce/js/tinymce/plugins/compat3x/form_utils.js new file mode 100644 index 00000000..69d338fc --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/compat3x/form_utils.js @@ -0,0 +1,210 @@ +/** + * form_utils.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme")); + +function getColorPickerHTML(id, target_form_element) { + var h = "", dom = tinyMCEPopup.dom; + + if (label = dom.select('label[for=' + target_form_element + ']')[0]) { + label.id = label.id || dom.uniqueId(); + } + + h += '<a role="button" aria-labelledby="' + id + '_label" id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element +'\');" onmousedown="return false;" class="pickcolor">'; + h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> <span id="' + id + '_label" class="mceVoiceLabel mceIconOnly" style="display:none;">' + tinyMCEPopup.getLang('browse') + '</span></span></a>'; + + return h; +} + +function updateColor(img_id, form_element_id) { + document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value; +} + +function setBrowserDisabled(id, state) { + var img = document.getElementById(id); + var lnk = document.getElementById(id + "_link"); + + if (lnk) { + if (state) { + lnk.setAttribute("realhref", lnk.getAttribute("href")); + lnk.removeAttribute("href"); + tinyMCEPopup.dom.addClass(img, 'disabled'); + } else { + if (lnk.getAttribute("realhref")) + lnk.setAttribute("href", lnk.getAttribute("realhref")); + + tinyMCEPopup.dom.removeClass(img, 'disabled'); + } + } +} + +function getBrowserHTML(id, target_form_element, type, prefix) { + var option = prefix + "_" + type + "_browser_callback", cb, html; + + cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback")); + + if (!cb) + return ""; + + html = ""; + html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">'; + html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"> </span></a>'; + + return html; +} + +function openBrowser(img_id, target_form_element, type, option) { + var img = document.getElementById(img_id); + + if (img.className != "mceButtonDisabled") + tinyMCEPopup.openBrowser(target_form_element, type, option); +} + +function selectByValue(form_obj, field_name, value, add_custom, ignore_case) { + if (!form_obj || !form_obj.elements[field_name]) + return; + + if (!value) + value = ""; + + var sel = form_obj.elements[field_name]; + + var found = false; + for (var i=0; i<sel.options.length; i++) { + var option = sel.options[i]; + + if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) { + option.selected = true; + found = true; + } else + option.selected = false; + } + + if (!found && add_custom && value != '') { + var option = new Option(value, value); + option.selected = true; + sel.options[sel.options.length] = option; + sel.selectedIndex = sel.options.length - 1; + } + + return found; +} + +function getSelectValue(form_obj, field_name) { + var elm = form_obj.elements[field_name]; + + if (elm == null || elm.options == null || elm.selectedIndex === -1) + return ""; + + return elm.options[elm.selectedIndex].value; +} + +function addSelectValue(form_obj, field_name, name, value) { + var s = form_obj.elements[field_name]; + var o = new Option(name, value); + s.options[s.options.length] = o; +} + +function addClassesToList(list_id, specific_option) { + // Setup class droplist + var styleSelectElm = document.getElementById(list_id); + var styles = tinyMCEPopup.getParam('theme_advanced_styles', false); + styles = tinyMCEPopup.getParam(specific_option, styles); + + if (styles) { + var stylesAr = styles.split(';'); + + for (var i=0; i<stylesAr.length; i++) { + if (stylesAr != "") { + var key, value; + + key = stylesAr[i].split('=')[0]; + value = stylesAr[i].split('=')[1]; + + styleSelectElm.options[styleSelectElm.length] = new Option(key, value); + } + } + } else { + tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) { + styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']); + }); + } +} + +function isVisible(element_id) { + var elm = document.getElementById(element_id); + + return elm && elm.style.display != "none"; +} + +function convertRGBToHex(col) { + var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); + + var rgb = col.replace(re, "$1,$2,$3").split(','); + if (rgb.length == 3) { + r = parseInt(rgb[0]).toString(16); + g = parseInt(rgb[1]).toString(16); + b = parseInt(rgb[2]).toString(16); + + r = r.length == 1 ? '0' + r : r; + g = g.length == 1 ? '0' + g : g; + b = b.length == 1 ? '0' + b : b; + + return "#" + r + g + b; + } + + return col; +} + +function convertHexToRGB(col) { + if (col.indexOf('#') != -1) { + col = col.replace(new RegExp('[^0-9A-F]', 'gi'), ''); + + r = parseInt(col.substring(0, 2), 16); + g = parseInt(col.substring(2, 4), 16); + b = parseInt(col.substring(4, 6), 16); + + return "rgb(" + r + "," + g + "," + b + ")"; + } + + return col; +} + +function trimSize(size) { + return size.replace(/([0-9\.]+)(px|%|in|cm|mm|em|ex|pt|pc)/i, '$1$2'); +} + +function getCSSSize(size) { + size = trimSize(size); + + if (size == "") + return ""; + + // Add px + if (/^[0-9]+$/.test(size)) + size += 'px'; + // Sanity check, IE doesn't like broken values + else if (!(/^[0-9\.]+(px|%|in|cm|mm|em|ex|pt|pc)$/i.test(size))) + return ""; + + return size; +} + +function getStyle(elm, attrib, style) { + var val = tinyMCEPopup.dom.getAttrib(elm, attrib); + + if (val != '') + return '' + val; + + if (typeof(style) == 'undefined') + style = attrib; + + return tinyMCEPopup.dom.getStyle(elm, style); +} diff --git a/extlib/tinymce/js/tinymce/plugins/compat3x/mctabs.js b/extlib/tinymce/js/tinymce/plugins/compat3x/mctabs.js new file mode 100644 index 00000000..acb5657e --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/compat3x/mctabs.js @@ -0,0 +1,162 @@ +/** + * mctabs.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +function MCTabs() { + this.settings = []; + this.onChange = tinyMCEPopup.editor.windowManager.createInstance('tinymce.util.Dispatcher'); +}; + +MCTabs.prototype.init = function(settings) { + this.settings = settings; +}; + +MCTabs.prototype.getParam = function(name, default_value) { + var value = null; + + value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name]; + + // Fix bool values + if (value == "true" || value == "false") + return (value == "true"); + + return value; +}; + +MCTabs.prototype.showTab =function(tab){ + tab.className = 'current'; + tab.setAttribute("aria-selected", true); + tab.setAttribute("aria-expanded", true); + tab.tabIndex = 0; +}; + +MCTabs.prototype.hideTab =function(tab){ + var t=this; + + tab.className = ''; + tab.setAttribute("aria-selected", false); + tab.setAttribute("aria-expanded", false); + tab.tabIndex = -1; +}; + +MCTabs.prototype.showPanel = function(panel) { + panel.className = 'current'; + panel.setAttribute("aria-hidden", false); +}; + +MCTabs.prototype.hidePanel = function(panel) { + panel.className = 'panel'; + panel.setAttribute("aria-hidden", true); +}; + +MCTabs.prototype.getPanelForTab = function(tabElm) { + return tinyMCEPopup.dom.getAttrib(tabElm, "aria-controls"); +}; + +MCTabs.prototype.displayTab = function(tab_id, panel_id, avoid_focus) { + var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i, t = this; + + tabElm = document.getElementById(tab_id); + + if (panel_id === undefined) { + panel_id = t.getPanelForTab(tabElm); + } + + panelElm= document.getElementById(panel_id); + panelContainerElm = panelElm ? panelElm.parentNode : null; + tabContainerElm = tabElm ? tabElm.parentNode : null; + selectionClass = t.getParam('selection_class', 'current'); + + if (tabElm && tabContainerElm) { + nodes = tabContainerElm.childNodes; + + // Hide all other tabs + for (i = 0; i < nodes.length; i++) { + if (nodes[i].nodeName == "LI") { + t.hideTab(nodes[i]); + } + } + + // Show selected tab + t.showTab(tabElm); + } + + if (panelElm && panelContainerElm) { + nodes = panelContainerElm.childNodes; + + // Hide all other panels + for (i = 0; i < nodes.length; i++) { + if (nodes[i].nodeName == "DIV") + t.hidePanel(nodes[i]); + } + + if (!avoid_focus) { + tabElm.focus(); + } + + // Show selected panel + t.showPanel(panelElm); + } +}; + +MCTabs.prototype.getAnchor = function() { + var pos, url = document.location.href; + + if ((pos = url.lastIndexOf('#')) != -1) + return url.substring(pos + 1); + + return ""; +}; + + +//Global instance +var mcTabs = new MCTabs(); + +tinyMCEPopup.onInit.add(function() { + var tinymce = tinyMCEPopup.getWin().tinymce, dom = tinyMCEPopup.dom, each = tinymce.each; + + each(dom.select('div.tabs'), function(tabContainerElm) { + var keyNav; + + dom.setAttrib(tabContainerElm, "role", "tablist"); + + var items = tinyMCEPopup.dom.select('li', tabContainerElm); + var action = function(id) { + mcTabs.displayTab(id, mcTabs.getPanelForTab(id)); + mcTabs.onChange.dispatch(id); + }; + + each(items, function(item) { + dom.setAttrib(item, 'role', 'tab'); + dom.bind(item, 'click', function(evt) { + action(item.id); + }); + }); + + dom.bind(dom.getRoot(), 'keydown', function(evt) { + if (evt.keyCode === 9 && evt.ctrlKey && !evt.altKey) { // Tab + keyNav.moveFocus(evt.shiftKey ? -1 : 1); + tinymce.dom.Event.cancel(evt); + } + }); + + each(dom.select('a', tabContainerElm), function(a) { + dom.setAttrib(a, 'tabindex', '-1'); + }); + + keyNav = tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', { + root: tabContainerElm, + items: items, + onAction: action, + actOnFocus: true, + enableLeftRight: true, + enableUpDown: true + }, tinyMCEPopup.dom); + }); +});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/compat3x/tiny_mce_popup.js b/extlib/tinymce/js/tinymce/plugins/compat3x/tiny_mce_popup.js new file mode 100644 index 00000000..6ed0d5e9 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/compat3x/tiny_mce_popup.js @@ -0,0 +1,435 @@ +/** + * Popup.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +// Some global instances +var tinymce = null, tinyMCEPopup, tinyMCE; + +/** + * TinyMCE popup/dialog helper class. This gives you easy access to the + * parent editor instance and a bunch of other things. It's higly recommended + * that you load this script into your dialogs. + * + * @static + * @class tinyMCEPopup + */ +tinyMCEPopup = { + /** + * Initializes the popup this will be called automatically. + * + * @method init + */ + init : function() { + var t = this, w, ti, settings; + + // Find window & API + w = t.getWin(); + tinymce = w.tinymce; + tinyMCE = w.tinyMCE; + t.editor = tinymce.EditorManager.activeEditor; + t.params = t.editor.windowManager.params; + t.features = t.editor.windowManager.features; + settings = t.editor.settings; + + // Setup popup CSS path(s) + if (settings.popup_css !== false) { + if (settings.popup_css) { + settings.popup_css = t.documentBaseURI.toAbsolute(settings.popup_css); + } else { + settings.popup_css = t.baseURI.toAbsolute("themes/" + settings.theme + "/skins/" + settings.skin + "/dialog.css"); + } + } + + if (settings.popup_css_add) { + settings.popup_css += ',' + t.documentBaseURI.toAbsolute(settings.popup_css_add); + } + + // Setup local DOM + t.dom = t.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document, {ownEvents: true, proxy: tinyMCEPopup._eventProxy}); + t.dom.bind(window, 'ready', t._onDOMLoaded, t); + + // Enables you to skip loading the default css + if (t.features.popup_css !== false) + t.dom.loadCSS(t.features.popup_css || t.editor.settings.popup_css); + + // Setup on init listeners + t.listeners = []; + + /** + * Fires when the popup is initialized. + * + * @event onInit + * @param {tinymce.Editor} editor Editor instance. + * @example + * // Alerts the selected contents when the dialog is loaded + * tinyMCEPopup.onInit.add(function(ed) { + * alert(ed.selection.getContent()); + * }); + * + * // Executes the init method on page load in some object using the SomeObject scope + * tinyMCEPopup.onInit.add(SomeObject.init, SomeObject); + */ + t.onInit = { + add : function(f, s) { + t.listeners.push({func : f, scope : s}); + } + }; + + t.isWindow = !t.getWindowArg('mce_inline'); + t.id = t.getWindowArg('mce_window_id'); + }, + + /** + * Returns the reference to the parent window that opened the dialog. + * + * @method getWin + * @return {Window} Reference to the parent window that opened the dialog. + */ + getWin : function() { + // Added frameElement check to fix bug: #2817583 + return (!window.frameElement && window.dialogArguments) || opener || parent || top; + }, + + /** + * Returns a window argument/parameter by name. + * + * @method getWindowArg + * @param {String} n Name of the window argument to retrive. + * @param {String} dv Optional default value to return. + * @return {String} Argument value or default value if it wasn't found. + */ + getWindowArg : function(n, dv) { + var v = this.params[n]; + + return tinymce.is(v) ? v : dv; + }, + + /** + * Returns a editor parameter/config option value. + * + * @method getParam + * @param {String} n Name of the editor config option to retrive. + * @param {String} dv Optional default value to return. + * @return {String} Parameter value or default value if it wasn't found. + */ + getParam : function(n, dv) { + return this.editor.getParam(n, dv); + }, + + /** + * Returns a language item by key. + * + * @method getLang + * @param {String} n Language item like mydialog.something. + * @param {String} dv Optional default value to return. + * @return {String} Language value for the item like "my string" or the default value if it wasn't found. + */ + getLang : function(n, dv) { + return this.editor.getLang(n, dv); + }, + + /** + * Executed a command on editor that opened the dialog/popup. + * + * @method execCommand + * @param {String} cmd Command to execute. + * @param {Boolean} ui Optional boolean value if the UI for the command should be presented or not. + * @param {Object} val Optional value to pass with the comman like an URL. + * @param {Object} a Optional arguments object. + */ + execCommand : function(cmd, ui, val, a) { + a = a || {}; + a.skip_focus = 1; + + this.restoreSelection(); + return this.editor.execCommand(cmd, ui, val, a); + }, + + /** + * Resizes the dialog to the inner size of the window. This is needed since various browsers + * have different border sizes on windows. + * + * @method resizeToInnerSize + */ + resizeToInnerSize : function() { + var t = this; + + // Detach it to workaround a Chrome specific bug + // https://sourceforge.net/tracker/?func=detail&atid=635682&aid=2926339&group_id=103281 + setTimeout(function() { + var vp = t.dom.getViewPort(window); + + t.editor.windowManager.resizeBy( + t.getWindowArg('mce_width') - vp.w, + t.getWindowArg('mce_height') - vp.h, + t.id || window + ); + }, 10); + }, + + /** + * Will executed the specified string when the page has been loaded. This function + * was added for compatibility with the 2.x branch. + * + * @method executeOnLoad + * @param {String} s String to evalutate on init. + */ + executeOnLoad : function(s) { + this.onInit.add(function() { + eval(s); + }); + }, + + /** + * Stores the current editor selection for later restoration. This can be useful since some browsers + * looses it's selection if a control element is selected/focused inside the dialogs. + * + * @method storeSelection + */ + storeSelection : function() { + this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark(1); + }, + + /** + * Restores any stored selection. This can be useful since some browsers + * looses it's selection if a control element is selected/focused inside the dialogs. + * + * @method restoreSelection + */ + restoreSelection : function() { + var t = tinyMCEPopup; + + if (!t.isWindow && tinymce.isIE) + t.editor.selection.moveToBookmark(t.editor.windowManager.bookmark); + }, + + /** + * Loads a specific dialog language pack. If you pass in plugin_url as a argument + * when you open the window it will load the <plugin url>/langs/<code>_dlg.js lang pack file. + * + * @method requireLangPack + */ + requireLangPack : function() { + var t = this, u = t.getWindowArg('plugin_url') || t.getWindowArg('theme_url'); + + if (u && t.editor.settings.language && t.features.translate_i18n !== false && t.editor.settings.language_load !== false) { + u += '/langs/' + t.editor.settings.language + '_dlg.js'; + + if (!tinymce.ScriptLoader.isDone(u)) { + document.write('<script type="text/javascript" src="' + u + '"></script>'); + tinymce.ScriptLoader.markDone(u); + } + } + }, + + /** + * Executes a color picker on the specified element id. When the user + * then selects a color it will be set as the value of the specified element. + * + * @method pickColor + * @param {DOMEvent} e DOM event object. + * @param {string} element_id Element id to be filled with the color value from the picker. + */ + pickColor : function(e, element_id) { + this.execCommand('mceColorPicker', true, { + color : document.getElementById(element_id).value, + func : function(c) { + document.getElementById(element_id).value = c; + + try { + document.getElementById(element_id).onchange(); + } catch (ex) { + // Try fire event, ignore errors + } + } + }); + }, + + /** + * Opens a filebrowser/imagebrowser this will set the output value from + * the browser as a value on the specified element. + * + * @method openBrowser + * @param {string} element_id Id of the element to set value in. + * @param {string} type Type of browser to open image/file/flash. + * @param {string} option Option name to get the file_broswer_callback function name from. + */ + openBrowser : function(element_id, type, option) { + tinyMCEPopup.restoreSelection(); + this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window); + }, + + /** + * Creates a confirm dialog. Please don't use the blocking behavior of this + * native version use the callback method instead then it can be extended. + * + * @method confirm + * @param {String} t Title for the new confirm dialog. + * @param {function} cb Callback function to be executed after the user has selected ok or cancel. + * @param {Object} s Optional scope to execute the callback in. + */ + confirm : function(t, cb, s) { + this.editor.windowManager.confirm(t, cb, s, window); + }, + + /** + * Creates a alert dialog. Please don't use the blocking behavior of this + * native version use the callback method instead then it can be extended. + * + * @method alert + * @param {String} t Title for the new alert dialog. + * @param {function} cb Callback function to be executed after the user has selected ok. + * @param {Object} s Optional scope to execute the callback in. + */ + alert : function(tx, cb, s) { + this.editor.windowManager.alert(tx, cb, s, window); + }, + + /** + * Closes the current window. + * + * @method close + */ + close : function() { + var t = this; + + // To avoid domain relaxing issue in Opera + function close() { + t.editor.windowManager.close(window); + tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup + }; + + if (tinymce.isOpera) + t.getWin().setTimeout(close, 0); + else + close(); + }, + + // Internal functions + + _restoreSelection : function() { + var e = window.event.srcElement; + + if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button')) + tinyMCEPopup.restoreSelection(); + }, + +/* _restoreSelection : function() { + var e = window.event.srcElement; + + // If user focus a non text input or textarea + if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text') + tinyMCEPopup.restoreSelection(); + },*/ + + _onDOMLoaded : function() { + var t = tinyMCEPopup, ti = document.title, bm, h, nv; + + // Translate page + if (t.features.translate_i18n !== false) { + h = document.body.innerHTML; + + // Replace a=x with a="x" in IE + if (tinymce.isIE) + h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"') + + document.dir = t.editor.getParam('directionality',''); + + if ((nv = t.editor.translate(h)) && nv != h) + document.body.innerHTML = nv; + + if ((nv = t.editor.translate(ti)) && nv != ti) + document.title = ti = nv; + } + + if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow) + t.dom.addClass(document.body, 'forceColors'); + + document.body.style.display = ''; + + // Restore selection in IE when focus is placed on a non textarea or input element of the type text + if (tinymce.isIE) { + document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection); + + // Add base target element for it since it would fail with modal dialogs + t.dom.add(t.dom.select('head')[0], 'base', {target : '_self'}); + } + + t.restoreSelection(); + t.resizeToInnerSize(); + + // Set inline title + if (!t.isWindow) + t.editor.windowManager.setTitle(window, ti); + else + window.focus(); + + if (!tinymce.isIE && !t.isWindow) { + t.dom.bind(document, 'focus', function() { + t.editor.windowManager.focus(t.id); + }); + } + + // Patch for accessibility + tinymce.each(t.dom.select('select'), function(e) { + e.onkeydown = tinyMCEPopup._accessHandler; + }); + + // Call onInit + // Init must be called before focus so the selection won't get lost by the focus call + tinymce.each(t.listeners, function(o) { + o.func.call(o.scope, t.editor); + }); + + // Move focus to window + if (t.getWindowArg('mce_auto_focus', true)) { + window.focus(); + + // Focus element with mceFocus class + tinymce.each(document.forms, function(f) { + tinymce.each(f.elements, function(e) { + if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) { + e.focus(); + return false; // Break loop + } + }); + }); + } + + document.onkeyup = tinyMCEPopup._closeWinKeyHandler; + }, + + _accessHandler : function(e) { + e = e || window.event; + + if (e.keyCode == 13 || e.keyCode == 32) { + var elm = e.target || e.srcElement; + + if (elm.onchange) + elm.onchange(); + + return tinymce.dom.Event.cancel(e); + } + }, + + _closeWinKeyHandler : function(e) { + e = e || window.event; + + if (e.keyCode == 27) + tinyMCEPopup.close(); + }, + + _eventProxy: function(id) { + return function(evt) { + tinyMCEPopup.dom.events.callNativeHandler(id, evt); + }; + } +}; + +tinyMCEPopup.init();
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/compat3x/validate.js b/extlib/tinymce/js/tinymce/plugins/compat3x/validate.js new file mode 100644 index 00000000..d13aaa1b --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/compat3x/validate.js @@ -0,0 +1,252 @@ +/** + * validate.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +/** + // String validation: + + if (!Validator.isEmail('myemail')) + alert('Invalid email.'); + + // Form validation: + + var f = document.forms['myform']; + + if (!Validator.isEmail(f.myemail)) + alert('Invalid email.'); +*/ + +var Validator = { + isEmail : function(s) { + return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$'); + }, + + isAbsUrl : function(s) { + return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$'); + }, + + isSize : function(s) { + return this.test(s, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$'); + }, + + isId : function(s) { + return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$'); + }, + + isEmpty : function(s) { + var nl, i; + + if (s.nodeName == 'SELECT' && s.selectedIndex < 1) + return true; + + if (s.type == 'checkbox' && !s.checked) + return true; + + if (s.type == 'radio') { + for (i=0, nl = s.form.elements; i<nl.length; i++) { + if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked) + return false; + } + + return true; + } + + return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s); + }, + + isNumber : function(s, d) { + return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$')); + }, + + test : function(s, p) { + s = s.nodeType == 1 ? s.value : s; + + return s == '' || new RegExp(p).test(s); + } +}; + +var AutoValidator = { + settings : { + id_cls : 'id', + int_cls : 'int', + url_cls : 'url', + number_cls : 'number', + email_cls : 'email', + size_cls : 'size', + required_cls : 'required', + invalid_cls : 'invalid', + min_cls : 'min', + max_cls : 'max' + }, + + init : function(s) { + var n; + + for (n in s) + this.settings[n] = s[n]; + }, + + validate : function(f) { + var i, nl, s = this.settings, c = 0; + + nl = this.tags(f, 'label'); + for (i=0; i<nl.length; i++) { + this.removeClass(nl[i], s.invalid_cls); + nl[i].setAttribute('aria-invalid', false); + } + + c += this.validateElms(f, 'input'); + c += this.validateElms(f, 'select'); + c += this.validateElms(f, 'textarea'); + + return c == 3; + }, + + invalidate : function(n) { + this.mark(n.form, n); + }, + + getErrorMessages : function(f) { + var nl, i, s = this.settings, field, msg, values, messages = [], ed = tinyMCEPopup.editor; + nl = this.tags(f, "label"); + for (i=0; i<nl.length; i++) { + if (this.hasClass(nl[i], s.invalid_cls)) { + field = document.getElementById(nl[i].getAttribute("for")); + values = { field: nl[i].textContent }; + if (this.hasClass(field, s.min_cls, true)) { + message = ed.getLang('invalid_data_min'); + values.min = this.getNum(field, s.min_cls); + } else if (this.hasClass(field, s.number_cls)) { + message = ed.getLang('invalid_data_number'); + } else if (this.hasClass(field, s.size_cls)) { + message = ed.getLang('invalid_data_size'); + } else { + message = ed.getLang('invalid_data'); + } + + message = message.replace(/{\#([^}]+)\}/g, function(a, b) { + return values[b] || '{#' + b + '}'; + }); + messages.push(message); + } + } + return messages; + }, + + reset : function(e) { + var t = ['label', 'input', 'select', 'textarea']; + var i, j, nl, s = this.settings; + + if (e == null) + return; + + for (i=0; i<t.length; i++) { + nl = this.tags(e.form ? e.form : e, t[i]); + for (j=0; j<nl.length; j++) { + this.removeClass(nl[j], s.invalid_cls); + nl[j].setAttribute('aria-invalid', false); + } + } + }, + + validateElms : function(f, e) { + var nl, i, n, s = this.settings, st = true, va = Validator, v; + + nl = this.tags(f, e); + for (i=0; i<nl.length; i++) { + n = nl[i]; + + this.removeClass(n, s.invalid_cls); + + if (this.hasClass(n, s.required_cls) && va.isEmpty(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.number_cls) && !va.isNumber(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true)) + st = this.mark(f, n); + + if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.email_cls) && !va.isEmail(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.size_cls) && !va.isSize(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.id_cls) && !va.isId(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.min_cls, true)) { + v = this.getNum(n, s.min_cls); + + if (isNaN(v) || parseInt(n.value) < parseInt(v)) + st = this.mark(f, n); + } + + if (this.hasClass(n, s.max_cls, true)) { + v = this.getNum(n, s.max_cls); + + if (isNaN(v) || parseInt(n.value) > parseInt(v)) + st = this.mark(f, n); + } + } + + return st; + }, + + hasClass : function(n, c, d) { + return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className); + }, + + getNum : function(n, c) { + c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0]; + c = c.replace(/[^0-9]/g, ''); + + return c; + }, + + addClass : function(n, c, b) { + var o = this.removeClass(n, c); + n.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c; + }, + + removeClass : function(n, c) { + c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); + return n.className = c != ' ' ? c : ''; + }, + + tags : function(f, s) { + return f.getElementsByTagName(s); + }, + + mark : function(f, n) { + var s = this.settings; + + this.addClass(n, s.invalid_cls); + n.setAttribute('aria-invalid', 'true'); + this.markLabels(f, n, s.invalid_cls); + + return false; + }, + + markLabels : function(f, n, ic) { + var nl, i; + + nl = this.tags(f, "label"); + for (i=0; i<nl.length; i++) { + if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id) + this.addClass(nl[i], ic); + } + + return null; + } +}; diff --git a/extlib/tinymce/js/tinymce/plugins/contextmenu/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/contextmenu/plugin.min.js new file mode 100644 index 00000000..4aabc706 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/contextmenu/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("contextmenu",function(e){var t;e.on("contextmenu",function(n){var i;if(n.preventDefault(),i=e.settings.contextmenu||"link image inserttable | cell row column deletetable",t)t.show();else{var o=[];tinymce.each(i.split(/[ ,]/),function(t){var n=e.menuItems[t];"|"==t&&(n={text:t}),n&&(n.shortcut="",o.push(n))});for(var a=0;a<o.length;a++)"|"==o[a].text&&(0===a||a==o.length-1)&&o.splice(a,1);t=new tinymce.ui.Menu({items:o,context:"contextmenu"}),t.renderTo(document.body)}var r={x:n.pageX,y:n.pageY};e.inline||(r=tinymce.DOM.getPos(e.getContentAreaContainer()),r.x+=n.clientX,r.y+=n.clientY),t.moveTo(r.x,r.y),e.on("remove",function(){t.remove(),t=null})})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/directionality/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/directionality/plugin.min.js new file mode 100644 index 00000000..60c7f9d5 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/directionality/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("directionality",function(e){function t(t){var n,i=e.dom,a=e.selection.getSelectedBlocks();a.length&&(n=i.getAttrib(a[0],"dir"),tinymce.each(a,function(e){i.getParent(e.parentNode,"*[dir='"+t+"']",i.getRoot())||(n!=t?i.setAttrib(e,"dir",t):i.setAttrib(e,"dir",null))}),e.nodeChanged())}function n(e){var t=[];return tinymce.each("h1 h2 h3 h4 h5 h6 div p".split(" "),function(n){t.push(n+"[dir="+e+"]")}),t.join(",")}e.addCommand("mceDirectionLTR",function(){t("ltr")}),e.addCommand("mceDirectionRTL",function(){t("rtl")}),e.addButton("ltr",{title:"Left to right",cmd:"mceDirectionLTR",stateSelector:n("ltr")}),e.addButton("rtl",{title:"Right to left",cmd:"mceDirectionRTL",stateSelector:n("rtl")})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-cool.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-cool.gif Binary files differnew file mode 100644 index 00000000..ba90cc36 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-cool.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-cry.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-cry.gif Binary files differnew file mode 100644 index 00000000..74d897a4 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-cry.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-embarassed.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-embarassed.gif Binary files differnew file mode 100644 index 00000000..963a96b8 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-embarassed.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif Binary files differnew file mode 100644 index 00000000..c7cf1011 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-frown.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-frown.gif Binary files differnew file mode 100644 index 00000000..716f55e1 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-frown.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-innocent.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-innocent.gif Binary files differnew file mode 100644 index 00000000..334d49e0 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-innocent.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-kiss.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-kiss.gif Binary files differnew file mode 100644 index 00000000..4efd549e --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-kiss.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-laughing.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-laughing.gif Binary files differnew file mode 100644 index 00000000..82c5b182 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-laughing.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-money-mouth.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-money-mouth.gif Binary files differnew file mode 100644 index 00000000..ca2451e1 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-money-mouth.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-sealed.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-sealed.gif Binary files differnew file mode 100644 index 00000000..fe66220c --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-sealed.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-smile.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-smile.gif Binary files differnew file mode 100644 index 00000000..fd27edfa --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-smile.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-surprised.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-surprised.gif Binary files differnew file mode 100644 index 00000000..0cc9bb71 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-surprised.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-tongue-out.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-tongue-out.gif Binary files differnew file mode 100644 index 00000000..2075dc16 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-tongue-out.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-undecided.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-undecided.gif Binary files differnew file mode 100644 index 00000000..bef7e257 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-undecided.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-wink.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-wink.gif Binary files differnew file mode 100644 index 00000000..0631c761 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-wink.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-yell.gif b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-yell.gif Binary files differnew file mode 100644 index 00000000..648e6e87 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/img/smiley-yell.gif diff --git a/extlib/tinymce/js/tinymce/plugins/emoticons/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/emoticons/plugin.min.js new file mode 100644 index 00000000..f70e7941 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/emoticons/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("emoticons",function(e,t){function n(){var e;return e='<table role="presentation" class="mce-grid">',tinymce.each(i,function(n){e+="<tr>",tinymce.each(n,function(n){var i=t+"/img/smiley-"+n+".gif";e+='<td><a href="#" data-mce-url="'+i+'" tabindex="-1"><img src="'+i+'" style="width: 18px; height: 18px"></a></td>'}),e+="</tr>"}),e+="</table>"}var i=[["cool","cry","embarassed","foot-in-mouth"],["frown","innocent","kiss","laughing"],["money-mouth","sealed","smile","surprised"],["tongue-out","undecided","wink","yell"]];e.addButton("emoticons",{type:"panelbutton",popoverAlign:"bc-tl",panel:{autohide:!0,html:n,onclick:function(t){var n=e.dom.getParent(t.target,"a");n&&(e.insertContent('<img src="'+n.getAttribute("data-mce-url")+'" />'),this.hide())}},tooltip:"Emoticons"})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/example/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/example/plugin.min.js new file mode 100644 index 00000000..24a64c8e --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/example/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("example",function(e){e.addButton("example",{text:"My button",icon:!1,onclick:function(){e.windowManager.open({title:"Example plugin",body:[{type:"textbox",name:"title",label:"Title"}],onsubmit:function(t){e.insertContent("Title: "+t.data.title)}})}}),e.addMenuItem("example",{text:"Example plugin",context:"tools",onclick:function(){e.windowManager.open({title:"TinyMCE site",url:"http://www.tinymce.com",width:800,height:600,buttons:[{text:"Close",onclick:"close"}]})}})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/example_dependency/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/example_dependency/plugin.min.js new file mode 100644 index 00000000..e61bf473 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/example_dependency/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("example_dependency",function(){},["example"]);
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/fullpage/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/fullpage/plugin.min.js new file mode 100644 index 00000000..0f15de46 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/fullpage/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("fullpage",function(e){function t(){var t=n();e.windowManager.open({title:"Document properties",data:t,defaults:{type:"textbox",size:40},body:[{name:"title",label:"Title"},{name:"keywords",label:"Keywords"},{name:"description",label:"Description"},{name:"robots",label:"Robots"},{name:"author",label:"Author"},{name:"docencoding",label:"Encoding"}],onSubmit:function(e){i(tinymce.extend(t,e.data))}})}function n(){function t(e,t){var n=e.attr(t);return n||""}var n,i,r=a(),o={};return o.fontface=e.getParam("fullpage_default_fontface",""),o.fontsize=e.getParam("fullpage_default_fontsize",""),n=r.firstChild,7==n.type&&(o.xml_pi=!0,i=/encoding="([^"]+)"/.exec(n.value),i&&(o.docencoding=i[1])),n=r.getAll("#doctype")[0],n&&(o.doctype="<!DOCTYPE"+n.value+">"),n=r.getAll("title")[0],n&&n.firstChild&&(o.title=n.firstChild.value),u(r.getAll("meta"),function(e){var t,n=e.attr("name"),i=e.attr("http-equiv");n?o[n.toLowerCase()]=e.attr("content"):"Content-Type"==i&&(t=/charset\s*=\s*(.*)\s*/gi.exec(e.attr("content")),t&&(o.docencoding=t[1]))}),n=r.getAll("html")[0],n&&(o.langcode=t(n,"lang")||t(n,"xml:lang")),n=r.getAll("link")[0],n&&"stylesheet"==n.attr("rel")&&(o.stylesheet=n.attr("href")),n=r.getAll("body")[0],n&&(o.langdir=t(n,"dir"),o.style=t(n,"style"),o.visited_color=t(n,"vlink"),o.link_color=t(n,"link"),o.active_color=t(n,"alink")),o}function i(t){function n(e,t,n){e.attr(t,n?n:void 0)}function i(e){o.firstChild?o.insert(e,o.firstChild):o.append(e)}var r,o,l,c,m,f=e.dom;r=a(),o=r.getAll("head")[0],o||(c=r.getAll("html")[0],o=new d("head",1),c.firstChild?c.insert(o,c.firstChild,!0):c.append(o)),c=r.firstChild,t.xml_pi?(m='version="1.0"',t.docencoding&&(m+=' encoding="'+t.docencoding+'"'),7!=c.type&&(c=new d("xml",7),r.insert(c,r.firstChild,!0)),c.value=m):c&&7==c.type&&c.remove(),c=r.getAll("#doctype")[0],t.doctype?(c||(c=new d("#doctype",10),t.xml_pi?r.insert(c,r.firstChild):i(c)),c.value=t.doctype.substring(9,t.doctype.length-1)):c&&c.remove(),t.docencoding&&(c=null,u(r.getAll("meta"),function(e){"Content-Type"==e.attr("http-equiv")&&(c=e)}),c||(c=new d("meta",1),c.attr("http-equiv","Content-Type"),c.shortEnded=!0,i(c)),c.attr("content","text/html; charset="+t.docencoding)),c=r.getAll("title")[0],t.title?c||(c=new d("title",1),c.append(new d("#text",3)).value=t.title,i(c)):c&&c.remove(),u("keywords,description,author,copyright,robots".split(","),function(e){var n,a,o=r.getAll("meta"),l=t[e];for(n=0;n<o.length;n++)if(a=o[n],a.attr("name")==e)return l?a.attr("content",l):a.remove(),void 0;l&&(c=new d("meta",1),c.attr("name",e),c.attr("content",l),c.shortEnded=!0,i(c))}),c=r.getAll("link")[0],c&&"stylesheet"==c.attr("rel")?t.stylesheet?c.attr("href",t.stylesheet):c.remove():t.stylesheet&&(c=new d("link",1),c.attr({rel:"stylesheet",text:"text/css",href:t.stylesheet}),c.shortEnded=!0,i(c)),c=r.getAll("body")[0],c&&(n(c,"dir",t.langdir),n(c,"style",t.style),n(c,"vlink",t.visited_color),n(c,"link",t.link_color),n(c,"alink",t.active_color),f.setAttribs(e.getBody(),{style:t.style,dir:t.dir,vLink:t.visited_color,link:t.link_color,aLink:t.active_color})),c=r.getAll("html")[0],c&&(n(c,"lang",t.langcode),n(c,"xml:lang",t.langcode)),o.firstChild||o.remove(),l=new tinymce.html.Serializer({validate:!1,indent:!0,apply_source_formatting:!0,indent_before:"head,html,body,meta,title,script,link,style",indent_after:"head,html,body,meta,title,script,link,style"}).serialize(r),s=l.substring(0,l.indexOf("</body>"))}function a(){return new tinymce.html.DomParser({validate:!1,root_name:"#document"}).parse(s)}function r(t){function n(e){return e.replace(/<\/?[A-Z]+/g,function(e){return e.toLowerCase()})}var i,r,l,d,m=t.content,f="",g=e.dom;t.selection||"raw"==t.format&&s||t.source_view&&e.getParam("fullpage_hide_in_source_view")||(m=m.replace(/<(\/?)BODY/gi,"<$1body"),i=m.indexOf("<body"),-1!=i?(i=m.indexOf(">",i),s=n(m.substring(0,i+1)),r=m.indexOf("</body",i),-1==r&&(r=m.length),t.content=m.substring(i+1,r),c=n(m.substring(r))):(s=o(),c="\n</body>\n</html>"),l=a(),u(l.getAll("style"),function(e){e.firstChild&&(f+=e.firstChild.value)}),d=l.getAll("body")[0],d&&g.setAttribs(e.getBody(),{style:d.attr("style")||"",dir:d.attr("dir")||"",vLink:d.attr("vlink")||"",link:d.attr("link")||"",aLink:d.attr("alink")||""}),g.remove("fullpage_styles"),f&&(g.add(e.getDoc().getElementsByTagName("head")[0],"style",{id:"fullpage_styles"},f),d=g.get("fullpage_styles"),d.styleSheet&&(d.styleSheet.cssText=f)))}function o(){var t,n="",i="";return e.getParam("fullpage_default_xml_pi")&&(n+='<?xml version="1.0" encoding="'+e.getParam("fullpage_default_encoding","ISO-8859-1")+'" ?>\n'),n+=e.getParam("fullpage_default_doctype","<!DOCTYPE html>"),n+="\n<html>\n<head>\n",(t=e.getParam("fullpage_default_title"))&&(n+="<title>"+t+"</title>\n"),(t=e.getParam("fullpage_default_encoding"))&&(n+='<meta http-equiv="Content-Type" content="text/html; charset='+t+'" />\n'),(t=e.getParam("fullpage_default_font_family"))&&(i+="font-family: "+t+";"),(t=e.getParam("fullpage_default_font_size"))&&(i+="font-size: "+t+";"),(t=e.getParam("fullpage_default_text_color"))&&(i+="color: "+t+";"),n+="</head>\n<body"+(i?' style="'+i+'"':"")+">\n"}function l(t){t.selection||t.source_view&&e.getParam("fullpage_hide_in_source_view")||(t.content=tinymce.trim(s)+"\n"+tinymce.trim(t.content)+"\n"+tinymce.trim(c))}var s,c,u=tinymce.each,d=tinymce.html.Node;e.addCommand("mceFullPageProperties",t),e.addButton("fullpage",{title:"Document properties",cmd:"mceFullPageProperties"}),e.addMenuItem("fullpage",{text:"Document properties",cmd:"mceFullPageProperties",context:"file"}),e.on("BeforeSetContent",r),e.on("GetContent",l)});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/fullscreen/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/fullscreen/plugin.min.js new file mode 100644 index 00000000..92a3b703 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/fullscreen/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("fullscreen",function(e){function t(){var e,t,n=window,i=document,a=i.body;return a.offsetWidth&&(e=a.offsetWidth,t=a.offsetHeight),n.innerWidth&&n.innerHeight&&(e=n.innerWidth,t=n.innerHeight),{w:e,h:t}}function n(){function n(){l.setStyle(c,"height",t().h-(s.clientHeight-c.clientHeight))}var s,c,u,d=document.body,m=document.documentElement;o=!o,s=e.getContainer().firstChild,c=e.getContentAreaContainer().firstChild,u=c.style,o?(i=u.width,a=u.height,u.width=u.height="100%",l.addClass(d,"mce-fullscreen"),l.addClass(m,"mce-fullscreen"),l.addClass(s,"mce-fullscreen"),l.bind(window,"resize",n),n(),r=n):(u.width=i,u.height=a,l.removeClass(d,"mce-fullscreen"),l.removeClass(m,"mce-fullscreen"),l.removeClass(s,"mce-fullscreen"),l.unbind(window,"resize",r)),e.fire("FullscreenStateChanged",{state:o})}var i,a,r,o=!1,l=tinymce.DOM;if(!e.settings.inline)return e.on("init",function(){e.addShortcut("Ctrl+Alt+F","",n)}),e.on("remove",function(){r&&l.unbind(window,"resize",r)}),e.addCommand("mceFullScreen",n),e.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Alt+F",selectable:!0,onClick:n,onPostRender:function(){var t=this;e.on("FullscreenStateChanged",function(e){t.active(e.state)})},context:"view"}),e.addButton("fullscreen",{tooltip:"Fullscreen",shortcut:"Ctrl+Alt+F",onClick:n,onPostRender:function(){var t=this;e.on("FullscreenStateChanged",function(e){t.active(e.state)})}}),{isFullscreen:function(){return o}}});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/hr/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/hr/plugin.min.js new file mode 100644 index 00000000..f9268ae0 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/hr/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("hr",function(e){e.addCommand("InsertHorizontalRule",function(){e.execCommand("mceInsertContent",!1,"<hr />")}),e.addButton("hr",{icon:"hr",tooltip:"Insert horizontal ruler",cmd:"InsertHorizontalRule"}),e.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/image/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/image/plugin.min.js new file mode 100644 index 00000000..7c3b8af4 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/image/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("image",function(e){function t(e,t){function n(e,n){i.parentNode.removeChild(i),t({width:e,height:n})}var i=document.createElement("img");i.onload=function(){n(i.clientWidth,i.clientHeight)},i.onerror=function(){n()},i.src=e;var a=i.style;a.visibility="hidden",a.position="fixed",a.bottom=a.left=0,a.width=a.height="auto",document.body.appendChild(i)}function n(t){return function(){var n=e.settings.image_list;"string"==typeof n?tinymce.util.XHR.send({url:n,success:function(e){t(tinymce.util.JSON.parse(e))}}):t(n)}}function i(n){function i(){var e=[{text:"None",value:""}];return tinymce.each(n,function(t){e.push({text:t.text||t.title,value:t.value||t.url,menu:t.menu})}),e}function a(e){var t,n,i,a;t=c.find("#width")[0],n=c.find("#height")[0],i=t.value(),a=n.value(),c.find("#constrain")[0].checked()&&u&&m&&i&&a&&(e.control==t?(a=Math.round(i/u*a),n.value(a)):(i=Math.round(a/m*i),t.value(i))),u=i,m=a}function r(){function t(t){function i(){t.onload=t.onerror=null,e.selection.select(t),e.nodeChanged()}t.onload=function(){n.width||n.height||f.setAttribs(t,{width:t.clientWidth,height:t.clientHeight}),i()},t.onerror=i}var n=c.toJSON();""===n.width&&(n.width=null),""===n.height&&(n.height=null),""===n.style&&(n.style=null),n={src:n.src,alt:n.alt,width:n.width,height:n.height,style:n.style},h?f.setAttribs(h,n):(n.id="__mcenew",e.insertContent(f.createHTML("img",n)),h=f.get("__mcenew"),f.setAttrib(h,"id",null)),t(h)}function o(e){return e&&(e=e.replace(/px$/,"")),e}function l(){t(this.value(),function(e){e.width&&e.height&&(u=e.width,m=e.height,c.find("#width").value(u),c.find("#height").value(m))})}function s(){function e(e){return e.length>0&&/^[0-9]+$/.test(e)&&(e+="px"),e}var t=c.toJSON(),n=f.parseStyle(t.style);delete n.margin,n["margin-top"]=n["margin-bottom"]=e(t.vspace),n["margin-left"]=n["margin-right"]=e(t.hspace),n["border-width"]=e(t.border),c.find("#style").value(f.serializeStyle(f.parseStyle(f.serializeStyle(n))))}var c,d,u,m,g,f=e.dom,h=e.selection.getNode();u=f.getAttrib(h,"width"),m=f.getAttrib(h,"height"),"IMG"!=h.nodeName||h.getAttribute("data-mce-object")?h=null:d={src:f.getAttrib(h,"src"),alt:f.getAttrib(h,"alt"),width:u,height:m},n&&(g={name:"target",type:"listbox",label:"Image list",values:i(),onselect:function(e){var t=c.find("#alt");(!t.value()||e.lastControl&&t.value()==e.lastControl.text())&&t.value(e.control.text()),c.find("#src").value(e.control.value())}});var p=[{name:"src",type:"filepicker",filetype:"image",label:"Source",autofocus:!0,onchange:l},g,{name:"alt",type:"textbox",label:"Image description"},{type:"container",label:"Dimensions",layout:"flex",direction:"row",align:"center",spacing:5,items:[{name:"width",type:"textbox",maxLength:3,size:3,onchange:a},{type:"label",text:"x"},{name:"height",type:"textbox",maxLength:3,size:3,onchange:a},{name:"constrain",type:"checkbox",checked:!0,text:"Constrain proportions"}]}];e.settings.image_advtab?(h&&(d.hspace=o(h.style.marginLeft||h.style.marginRight),d.vspace=o(h.style.marginTop||h.style.marginBottom),d.border=o(h.style.borderWidth),d.style=e.dom.serializeStyle(e.dom.parseStyle(e.dom.getAttrib(h,"style")))),c=e.windowManager.open({title:"Insert/edit image",data:d,bodyType:"tabpanel",body:[{title:"General",type:"form",items:p},{title:"Advanced",type:"form",pack:"start",items:[{label:"Style",name:"style",type:"textbox"},{type:"form",layout:"grid",packV:"start",columns:2,padding:0,alignH:["left","right"],defaults:{type:"textbox",maxWidth:50,onchange:s},items:[{label:"Vertical space",name:"vspace"},{label:"Horizontal space",name:"hspace"},{label:"Border",name:"border"}]}]}],onSubmit:r})):c=e.windowManager.open({title:"Edit image",data:d,body:p,onSubmit:r})}e.addButton("image",{icon:"image",tooltip:"Insert/edit image",onclick:n(i),stateSelector:"img:not([data-mce-object])"}),e.addMenuItem("image",{icon:"image",text:"Insert image",onclick:n(i),context:"insert",prependToContext:!0})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/insertdatetime/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/insertdatetime/plugin.min.js new file mode 100644 index 00000000..224554d4 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/insertdatetime/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("insertdatetime",function(e){function t(t,n){function i(e,t){if(e=""+e,e.length<t)for(var n=0;n<t-e.length;n++)e="0"+e;return e}return n=n||new Date,t=t.replace("%D","%m/%d/%Y"),t=t.replace("%r","%I:%M:%S %p"),t=t.replace("%Y",""+n.getFullYear()),t=t.replace("%y",""+n.getYear()),t=t.replace("%m",i(n.getMonth()+1,2)),t=t.replace("%d",i(n.getDate(),2)),t=t.replace("%H",""+i(n.getHours(),2)),t=t.replace("%M",""+i(n.getMinutes(),2)),t=t.replace("%S",""+i(n.getSeconds(),2)),t=t.replace("%I",""+((n.getHours()+11)%12+1)),t=t.replace("%p",""+(n.getHours()<12?"AM":"PM")),t=t.replace("%B",""+e.translate(l[n.getMonth()])),t=t.replace("%b",""+e.translate(o[n.getMonth()])),t=t.replace("%A",""+e.translate(r[n.getDay()])),t=t.replace("%a",""+e.translate(a[n.getDay()])),t=t.replace("%%","%")}function n(n){var i=t(n);if(e.settings.insertdatetime_element){var a;a=/%[HMSIp]/.test(n)?t("%Y-%m-%dT%H:%M"):t("%Y-%m-%d"),i='<time datetime="'+a+'">'+i+"</time>";var r=e.dom.getParent(e.selection.getStart(),"time");if(r)return e.dom.setOuterHTML(r,i),void 0}e.insertContent(i)}var i,a="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),r="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),o="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),l="January February March April May June July August September October November December".split(" "),s=[];e.addCommand("mceInsertDate",function(){n(e.getParam("insertdate_dateformat",e.translate("%Y-%m-%d")))}),e.addCommand("mceInsertTime",function(){n(e.getParam("insertdate_timeformat",e.translate("%H:%M:%S")))}),e.addButton("inserttime",{type:"splitbutton",title:"Insert time",onclick:function(){n(i||"%H:%M:%S")},menu:s}),tinymce.each(e.settings.insertdate_formats||["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"],function(e){s.push({text:t(e),onclick:function(){i=e,n(e)}})}),e.addMenuItem("insertdatetime",{icon:"date",text:"Insert date/time",menu:s,context:"insert"})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/layer/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/layer/plugin.min.js new file mode 100644 index 00000000..eb1ad4b6 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/layer/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("layer",function(e){function t(e){do if(e.className&&-1!=e.className.indexOf("mceItemLayer"))return e;while(e=e.parentNode)}function n(t){var n=e.dom;tinymce.each(n.select("div,p",t),function(e){/^(absolute|relative|fixed)$/i.test(e.style.position)&&(e.hasVisual?n.addClass(e,"mceItemVisualAid"):n.removeClass(e,"mceItemVisualAid"),n.addClass(e,"mceItemLayer"))})}function i(n){var i,o,a=[],r=t(e.selection.getNode()),l=-1,s=-1;for(o=[],tinymce.walk(e.getBody(),function(e){1==e.nodeType&&/^(absolute|relative|static)$/i.test(e.style.position)&&o.push(e)},"childNodes"),i=0;i<o.length;i++)a[i]=o[i].style.zIndex?parseInt(o[i].style.zIndex,10):0,0>l&&o[i]==r&&(l=i);if(0>n){for(i=0;i<a.length;i++)if(a[i]<a[l]){s=i;break}s>-1?(o[l].style.zIndex=a[s],o[s].style.zIndex=a[l]):a[l]>0&&(o[l].style.zIndex=a[l]-1)}else{for(i=0;i<a.length;i++)if(a[i]>a[l]){s=i;break}s>-1?(o[l].style.zIndex=a[s],o[s].style.zIndex=a[l]):o[l].style.zIndex=a[l]+1}e.execCommand("mceRepaint")}function o(){var t=e.dom,n=t.getPos(t.getParent(e.selection.getNode(),"*")),i=e.getBody();e.dom.add(i,"div",{style:{position:"absolute",left:n.x,top:n.y>20?n.y:20,width:100,height:100},"class":"mceItemVisualAid mceItemLayer"},e.selection.getContent()||e.getLang("layer.content")),tinymce.Env.ie&&t.setHTML(i,i.innerHTML)}function a(){var n=t(e.selection.getNode());n||(n=e.dom.getParent(e.selection.getNode(),"DIV,P,IMG")),n&&("absolute"==n.style.position.toLowerCase()?(e.dom.setStyles(n,{position:"",left:"",top:"",width:"",height:""}),e.dom.removeClass(n,"mceItemVisualAid"),e.dom.removeClass(n,"mceItemLayer")):(n.style.left||(n.style.left="20px"),n.style.top||(n.style.top="20px"),n.style.width||(n.style.width=n.width?n.width+"px":"100px"),n.style.height||(n.style.height=n.height?n.height+"px":"100px"),n.style.position="absolute",e.dom.setAttrib(n,"data-mce-style",""),e.addVisual(e.getBody())),e.execCommand("mceRepaint"),e.nodeChanged())}e.addCommand("mceInsertLayer",o),e.addCommand("mceMoveForward",function(){i(1)}),e.addCommand("mceMoveBackward",function(){i(-1)}),e.addCommand("mceMakeAbsolute",function(){a()}),e.addButton("moveforward",{title:"layer.forward_desc",cmd:"mceMoveForward"}),e.addButton("movebackward",{title:"layer.backward_desc",cmd:"mceMoveBackward"}),e.addButton("absolute",{title:"layer.absolute_desc",cmd:"mceMakeAbsolute"}),e.addButton("insertlayer",{title:"layer.insertlayer_desc",cmd:"mceInsertLayer"}),e.on("init",function(){tinymce.Env.ie&&e.getDoc().execCommand("2D-Position",!1,!0)}),e.on("mouseup",function(n){var i=t(n.target);i&&e.dom.setAttrib(i,"data-mce-style","")}),e.on("mousedown",function(n){var i,o=n.target,a=e.getDoc();tinymce.Env.gecko&&(t(o)?"on"!==a.designMode&&(a.designMode="on",o=a.body,i=o.parentNode,i.removeChild(o),i.appendChild(o)):"on"==a.designMode&&(a.designMode="off"))}),e.on("NodeChange",n)});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/legacyoutput/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/legacyoutput/plugin.min.js new file mode 100644 index 00000000..4f6f7c1a --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/legacyoutput/plugin.min.js @@ -0,0 +1 @@ +!function(e){e.on("AddEditor",function(e){e.editor.settings.inline_styles=!1}),e.PluginManager.add("legacyoutput",function(t){t.on("init",function(){var n="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img",i=e.explode(t.settings.font_size_style_values),o=t.schema;t.formatter.register({alignleft:{selector:n,attributes:{align:"left"}},aligncenter:{selector:n,attributes:{align:"center"}},alignright:{selector:n,attributes:{align:"right"}},alignjustify:{selector:n,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all"},{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all"},{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all"},{inline:"span",styles:{textDecoration:"underline"},exact:!0}],strikethrough:[{inline:"strike",remove:"all"},{inline:"span",styles:{textDecoration:"line-through"},exact:!0}],fontname:{inline:"font",attributes:{face:"%value"}},fontsize:{inline:"font",attributes:{size:function(t){return e.inArray(i,t.value)+1}}},forecolor:{inline:"font",attributes:{color:"%value"}},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"}}}),e.each("b,i,u,strike".split(","),function(e){o.addValidElements(e+"[*]")}),o.getElementRule("font")||o.addValidElements("font[face|size|color|style]"),e.each(n.split(","),function(e){var t=o.getElementRule(e);t&&(t.attributes.align||(t.attributes.align={},t.attributesOrder.push("align")))})})})}(tinymce);
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/link/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/link/plugin.min.js new file mode 100644 index 00000000..3387911c --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/link/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("link",function(t){function e(e){return function(){var n=t.settings.link_list;"string"==typeof n?tinymce.util.XHR.send({url:n,success:function(t){e(tinymce.util.JSON.parse(t))}}):e(n)}}function n(e){function n(t){var e=d.find("#text");(!e.value()||t.lastControl&&e.value()==t.lastControl.text())&&e.value(t.control.text()),d.find("#href").value(t.control.value())}function l(){var t=[{text:"None",value:""}];return tinymce.each(e,function(e){t.push({text:e.text||e.title,value:e.value||e.url,menu:e.menu})}),t}function i(e){var n=[{text:"None",value:""}];return tinymce.each(t.settings.rel_list,function(t){n.push({text:t.text||t.title,value:t.value,selected:e===t.value})}),n}function a(e){var n=[{text:"None",value:""}];return t.settings.target_list||n.push({text:"New window",value:"_blank"}),tinymce.each(t.settings.target_list,function(t){n.push({text:t.text||t.title,value:t.value,selected:e===t.value})}),n}function r(e){var l=[];return tinymce.each(t.dom.select("a:not([href])"),function(t){var n=t.name||t.id;n&&l.push({text:n,value:"#"+n,selected:-1!=e.indexOf("#"+n)})}),l.length?(l.unshift({text:"None",value:""}),{name:"anchor",type:"listbox",label:"Anchors",values:l,onselect:n}):void 0}function o(){c||0!==v.text.length||this.parent().parent().find("#text")[0].value(this.value())}var u,s,c,d,f,h,x,v={},g=t.selection,m=t.dom;u=g.getNode(),s=m.getParent(u,"a[href]"),s&&g.select(s),v.text=c=g.getContent({format:"text"}),v.href=s?m.getAttrib(s,"href"):"",v.target=s?m.getAttrib(s,"target"):"",v.rel=s?m.getAttrib(s,"rel"):"","IMG"==u.nodeName&&(v.text=c=" "),e&&(f={type:"listbox",label:"Link list",values:l(),onselect:n}),t.settings.target_list!==!1&&(x={name:"target",type:"listbox",label:"Target",values:a(v.target)}),t.settings.rel_list&&(h={name:"rel",type:"listbox",label:"Rel",values:i(v.rel)}),d=t.windowManager.open({title:"Insert link",data:v,body:[{name:"href",type:"filepicker",filetype:"file",size:40,autofocus:!0,label:"Url",onchange:o,onkeyup:o},{name:"text",type:"textbox",size:40,label:"Text to display",onchange:function(){v.text=this.value()}},r(v.href),f,h,x],onSubmit:function(e){function n(e,n){window.setTimeout(function(){t.windowManager.confirm(e,n)},0)}function l(){i.text!=c?s?(t.focus(),s.innerHTML=i.text,m.setAttribs(s,{href:a,target:i.target?i.target:null,rel:i.rel?i.rel:null}),g.select(s)):t.insertContent(m.createHTML("a",{href:a,target:i.target?i.target:null,rel:i.rel?i.rel:null},i.text)):t.execCommand("mceInsertLink",!1,{href:a,target:i.target,rel:i.rel?i.rel:null})}var i=e.data,a=i.href;return a?a.indexOf("@")>0&&-1==a.indexOf("//")&&-1==a.indexOf("mailto:")?(n("The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",function(t){t&&(a="mailto:"+a),l()}),void 0):/^\s*www\./i.test(a)?(n("The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",function(t){t&&(a="http://"+a),l()}),void 0):(l(),void 0):(t.execCommand("unlink"),void 0)}})}t.addButton("link",{icon:"link",tooltip:"Insert/edit link",shortcut:"Ctrl+K",onclick:e(n),stateSelector:"a[href]"}),t.addButton("unlink",{icon:"unlink",tooltip:"Remove link",cmd:"unlink",stateSelector:"a[href]"}),t.addShortcut("Ctrl+K","",e(n)),this.showDialog=n,t.addMenuItem("link",{icon:"link",text:"Insert link",shortcut:"Ctrl+K",onclick:e(n),stateSelector:"a[href]",context:"insert",prependToContext:!0})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/lists/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/lists/plugin.min.js new file mode 100644 index 00000000..1d4f342e --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/lists/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("lists",function(e){var t=this;e.on("init",function(){function n(e){function t(t){var i,a,r;a=e[t?"startContainer":"endContainer"],r=e[t?"startOffset":"endOffset"],1==a.nodeType&&(i=b.create("span",{"data-mce-type":"bookmark"}),a.hasChildNodes()?(r=Math.min(r,a.childNodes.length-1),a.insertBefore(i,a.childNodes[r])):a.appendChild(i),a=i,r=0),n[t?"startContainer":"endContainer"]=a,n[t?"startOffset":"endOffset"]=r}var n={};return t(!0),t(),n}function i(e){function t(t){function n(e){for(var t=e.parentNode.firstChild,n=0;t;){if(t==e)return n;(1!=t.nodeType||"bookmark"!=t.getAttribute("data-mce-type"))&&n++,t=t.nextSibling}return-1}var i,a,r;i=r=e[t?"startContainer":"endContainer"],a=e[t?"startOffset":"endOffset"],1==i.nodeType&&(t?(a=n(i),i=i.parentNode):(a=n(i),i=i.parentNode),b.remove(r)),e[t?"startContainer":"endContainer"]=i,e[t?"startOffset":"endOffset"]=a}t(!0),t();var n=b.createRng();n.setStart(e.startContainer,e.startOffset),n.setEnd(e.endContainer,e.endOffset),x.setRng(n)}function a(e){return e&&/^(OL|UL)$/.test(e.nodeName)}function r(e){return e.parentNode.firstChild==e}function o(e){return e.parentNode.lastChild==e}function l(t){return t&&!!e.schema.getTextBlockElements()[t.nodeName]}function s(t,n){var i,a;if(e.settings.forced_root_block&&(n=n||e.settings.forced_root_block),a=n?b.create(n):b.createFragment(),t)for(;i=t.firstChild;)a.appendChild(i);return e.settings.forced_root_block||a.appendChild(b.create("br")),a.hasChildNodes()||tinymce.isIE||(a.innerHTML='<br data-mce-bogus="1">'),a}function c(){return tinymce.grep(x.getSelectedBlocks(),function(e){return"LI"==e.nodeName})}function d(){return tinymce.grep(x.getSelectedBlocks(),l)}function u(e,t,n){var i,a;n=n||s(t),i=b.createRng(),i.setStartAfter(t),i.setEndAfter(e),a=i.extractContents(),b.isEmpty(a)||b.insertAfter(a,e),b.isEmpty(n)||b.insertAfter(n,e),b.isEmpty(t.parentNode)&&b.remove(t.parentNode),b.remove(t)}function m(e){var t,n;if(t=e.nextSibling,t&&a(t)&&t.nodeName==e.nodeName){for(;n=t.firstChild;)e.appendChild(n);b.remove(t)}if(t=e.previousSibling,t&&a(t)&&t.nodeName==e.nodeName){for(;n=t.firstChild;)e.insertBefore(n,e.firstChild);b.remove(t)}}function f(e){tinymce.each(tinymce.grep(b.select("ol,ul",e)),function(e){var t,n=e.parentNode;"LI"==n.nodeName&&n.firstChild==e&&(t=n.previousSibling,t&&"LI"==t.nodeName&&(t.appendChild(e),b.isEmpty(n)&&b.remove(n))),a(n)&&(t=n.previousSibling,t&&"LI"==t.nodeName&&t.appendChild(e))})}function g(){var e,t=n(x.getRng(!0));return tinymce.each(c(),function(t){var n,i;return n=t.previousSibling,n&&"UL"==n.nodeName?(n.appendChild(t),void 0):n&&"LI"==n.nodeName&&a(n.lastChild)?(n.lastChild.appendChild(t),void 0):(n=t.nextSibling,n&&"UL"==n.nodeName?(n.insertBefore(t,n.firstChild),void 0):(n&&"LI"==n.nodeName&&a(t.lastChild)||(n=t.previousSibling,n&&"LI"==n.nodeName&&(i=b.create(t.parentNode.nodeName),n.appendChild(i),i.appendChild(t)),e=!0),void 0))}),i(t),e}function p(){function e(e){b.isEmpty(e)&&b.remove(e)}var t,l=n(x.getRng(!0));return tinymce.each(c(),function(n){var i,l=n.parentNode,c=l.parentNode;if(r(n)&&o(n))if("LI"==c.nodeName)b.insertAfter(n,c),e(c);else{if(!a(c))return;b.remove(l,!0)}else if(r(n))if("LI"==c.nodeName)b.insertAfter(n,c),i=b.create("LI"),i.appendChild(l),b.insertAfter(i,n),e(c);else{if(!a(c))return;c.insertBefore(n,l)}else if(o(n))if("LI"==c.nodeName)b.insertAfter(n,c);else{if(!a(c))return;b.insertAfter(n,l)}else{if("LI"==c.nodeName)l=c,i=s(n,"LI");else{if(!a(c))return;i=s(n,"LI")}u(l,n,i),f(l.parentNode)}t=!0}),i(l),t}function h(t){function r(){function t(t){var n,i,a=e.getBody();for(n=o[t?"startContainer":"endContainer"],i=o[t?"startOffset":"endOffset"],1==n.nodeType&&(n=n.childNodes[Math.min(i,n.childNodes.length-1)]||n);n.parentNode!=a;){if(l(n))return n;if(/^(TD|TH)$/.test(n.parentNode.nodeName))return n;n=n.parentNode}return n}function n(e,t){var n,i=[];if(!l(e)){for(;e&&(n=e[t?"previousSibling":"nextSibling"],!b.isBlock(n)&&n);)e=n;for(;e;)i.push(e),e=e[t?"nextSibling":"previousSibling"]}return i}var i,a,r=t(!0),s=t();a=n(r,!0),r!=s&&(a=a.concat(n(s).reverse())),tinymce.each(a,function(e){if(!b.isBlock(e)||"BR"==e.nodeName){if(!i||"BR"==e.nodeName){if("BR"==e.nodeName&&(!e.nextSibling||b.isBlock(e.nextSibling)&&"BR"!=e.nextSibling.nodeName))return b.remove(e),!1;i=b.create("p"),c.push(i),e.parentNode.insertBefore(i,e)}return"BR"!=e.nodeName?i.appendChild(e):b.remove(e),e==s?!1:void 0}})}var o=x.getRng(!0),s=n(o),c=d();r(),tinymce.each(c,function(e){var n,i;i=e.previousSibling,i&&a(i)&&i.nodeName==t?(n=i,e=b.rename(e,"LI"),i.appendChild(e)):(n=b.create(t),e.parentNode.insertBefore(n,e),n.appendChild(e),e=b.rename(e,"LI")),m(n)}),i(s)}function y(){var e=n(x.getRng(!0));tinymce.each(c(),function(e){var t,n;for(t=e;t;t=t.parentNode)a(t)&&(n=t);u(n,e)}),i(e)}function v(e){var t=b.getParent(x.getStart(),"OL,UL");if(t)if(t.nodeName==e)y(e);else{var a=n(x.getRng(!0));m(b.rename(t,e)),i(a)}else h(e)}var b=e.dom,x=e.selection;t.backspaceDelete=function(e){function t(e,t){var n=e.startContainer,i=e.startOffset;if(3==n.nodeType&&(t?i<n.data.length:i>0))return n;for(var a=new tinymce.dom.TreeWalker(e.startContainer);n=a[t?"next":"prev"]();)if(3==n.nodeType&&n.data.length>0)return n}function r(e,t){var n,i,r=e.parentNode;for(a(t.lastChild)&&(i=t.lastChild),n=t.lastChild,n&&"BR"==n.nodeName&&e.hasChildNodes()&&b.remove(n);n=e.firstChild;)t.appendChild(n);i&&t.appendChild(i),b.remove(e),b.isEmpty(r)&&b.remove(r)}if(x.isCollapsed()){var o=b.getParent(x.getStart(),"LI");if(o){var l=x.getRng(!0),s=b.getParent(t(l,e),"LI");if(s&&s!=o){var c=n(l);return e?r(s,o):r(o,s),i(c),!0}if(!s&&!e&&y(o.parentNode.nodeName))return!0}}},e.addCommand("Indent",function(){return g()?void 0:!0}),e.addCommand("Outdent",function(){return p()?void 0:!0}),e.addCommand("InsertUnorderedList",function(){v("UL")}),e.addCommand("InsertOrderedList",function(){v("OL")})}),e.on("keydown",function(e){e.keyCode==tinymce.util.VK.BACKSPACE?t.backspaceDelete()&&e.preventDefault():e.keyCode==tinymce.util.VK.DELETE&&t.backspaceDelete(!0)&&e.preventDefault()})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/media/moxieplayer.swf b/extlib/tinymce/js/tinymce/plugins/media/moxieplayer.swf Binary files differnew file mode 100644 index 00000000..19c771be --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/media/moxieplayer.swf diff --git a/extlib/tinymce/js/tinymce/plugins/media/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/media/plugin.min.js new file mode 100644 index 00000000..3842ec81 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/media/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("media",function(e,t){function n(e){return-1!=e.indexOf(".mp3")?"audio/mpeg":-1!=e.indexOf(".wav")?"audio/wav":-1!=e.indexOf(".mp4")?"video/mp4":-1!=e.indexOf(".webm")?"video/webm":-1!=e.indexOf(".ogg")?"video/ogg":""}function i(){function t(e){var t,a,r,o;t=n.find("#width")[0],a=n.find("#height")[0],r=t.value(),o=a.value(),n.find("#constrain")[0].checked()&&i&&s&&r&&o&&(e.control==t?(o=Math.round(r/i*o),a.value(o)):(r=Math.round(o/s*r),t.value(r))),i=r,s=o}var n,i,s,c;c=l(e.selection.getNode()),i=c.width,s=c.height,n=e.windowManager.open({title:"Insert/edit video",data:c,bodyType:"tabpanel",body:[{title:"General",type:"form",onShowTab:function(){this.fromJSON(o(this.next().find("#embed").value()))},items:[{name:"source1",type:"filepicker",filetype:"media",size:40,autofocus:!0,label:"Source"},{name:"source2",type:"filepicker",filetype:"media",size:40,label:"Alternative source"},{name:"poster",type:"filepicker",filetype:"image",size:40,label:"Poster"},{type:"container",label:"Dimensions",layout:"flex",direction:"row",align:"center",spacing:5,items:[{name:"width",type:"textbox",maxLength:3,size:3,onchange:t},{type:"label",text:"x"},{name:"height",type:"textbox",maxLength:3,size:3,onchange:t},{name:"constrain",type:"checkbox",checked:!0,text:"Constrain proportions"}]}]},{title:"Embed",type:"panel",layout:"flex",direction:"column",align:"stretch",padding:10,spacing:10,onShowTab:function(){this.find("#embed").value(r(this.parent().toJSON()))},items:[{type:"label",text:"Paste your embed code below:"},{type:"textbox",flex:1,name:"embed",value:a(),multiline:!0,label:"Source"}]}],onSubmit:function(){e.insertContent(r(this.toJSON()))}})}function a(){var t=e.selection.getNode();return t.getAttribute("data-mce-object")?e.selection.getContent():void 0}function r(i){var a="";return i.source1||(tinymce.extend(i,o(i.embed)),i.source1)?(i.source1=e.convertURL(i.source1,"source"),i.source2=e.convertURL(i.source2,"source"),i.source1mime=n(i.source1),i.source2mime=n(i.source2),i.poster=e.convertURL(i.poster,"poster"),i.flashPlayerUrl=e.convertURL(t+"/moxieplayer.swf","movie"),i.embed?a=s(i.embed,i,!0):(tinymce.each(c,function(e){var t,n,a;if(t=e.regex.exec(i.source1)){for(a=e.url,n=0;t[n];n++)a=a.replace("$"+n,function(){return t[n]});i.source1=a,i.type=e.type,i.width=e.w,i.height=e.h}}),i.width=i.width||300,i.height=i.height||150,tinymce.each(i,function(t,n){i[n]=e.dom.encode(t)}),"iframe"==i.type?a+='<iframe src="'+i.source1+'" width="'+i.width+'" height="'+i.height+'"></iframe>':-1!=i.source1mime.indexOf("audio")?e.settings.audio_template_callback?a=e.settings.audio_template_callback(i):a+='<audio controls="controls" src="'+i.source1+'">'+(i.source2?'\n<source src="'+i.source2+'"'+(i.source2mime?' type="'+i.source2mime+'"':"")+" />\n":"")+"</audio>":a=e.settings.video_template_callback?e.settings.video_template_callback(i):'<video width="'+i.width+'" height="'+i.height+'"'+(i.poster?' poster="'+i.poster+'"':"")+' controls="controls">\n'+'<source src="'+i.source1+'"'+(i.source1mime?' type="'+i.source1mime+'"':"")+" />\n"+(i.source2?'<source src="'+i.source2+'"'+(i.source2mime?' type="'+i.source2mime+'"':"")+" />\n":"")+"</video>"),a):""}function o(e){var t={};return new tinymce.html.SaxParser({validate:!1,special:"script,noscript",start:function(e,n){t.source1||"param"!=e||(t.source1=n.map.movie),("iframe"==e||"object"==e||"embed"==e||"video"==e||"audio"==e)&&(t=tinymce.extend(n.map,t)),"source"==e&&(t.source1?t.source2||(t.source2=n.map.src):t.source1=n.map.src)}}).parse(e),t.source1=t.source1||t.src||t.data,t.source2=t.source2||"",t.poster=t.poster||"",t}function l(t){return t.getAttribute("data-mce-object")?o(e.serializer.serialize(t,{selection:!0})):{}}function s(e,t,n){function i(e,t){var n,i,a,r;for(n in t)if(a=""+t[n],e.map[n])for(i=e.length;i--;)r=e[i],r.name==n&&(a?(e.map[n]=a,r.value=a):(delete e.map[n],e.splice(i,1)));else a&&(e.push({name:n,value:a}),e.map[n]=a)}var a=new tinymce.html.Writer,r=0;return new tinymce.html.SaxParser({validate:!1,special:"script,noscript",comment:function(e){a.comment(e)},cdata:function(e){a.cdata(e)},text:function(e,t){a.text(e,t)},start:function(e,o,l){switch(e){case"video":case"object":case"img":case"iframe":i(o,{width:t.width,height:t.height})}if(n)switch(e){case"video":i(o,{poster:t.poster,src:""}),t.source2&&i(o,{src:""});break;case"iframe":i(o,{src:t.source1});break;case"source":if(r++,2>=r&&(i(o,{src:t["source"+r],type:t["source"+r+"mime"]}),!t["source"+r]))return}a.start(e,o,l)},end:function(e){if("video"==e&&n)for(var o=1;2>=o;o++)if(t["source"+o]){var l=[];l.map={},o>r&&(i(l,{src:t["source"+o],type:t["source"+o+"mime"]}),a.start("source",l,!0))}a.end(e)}},new tinymce.html.Schema({})).parse(e),a.getContent()}var c=[{regex:/youtu\.be\/([a-z1-9.-_]+)/,type:"iframe",w:425,h:350,url:"http://www.youtube.com/embed/$1"},{regex:/youtube\.com(.+)v=([^&]+)/,type:"iframe",w:425,h:350,url:"http://www.youtube.com/embed/$2"},{regex:/vimeo\.com\/([0-9]+)/,type:"iframe",w:425,h:350,url:"http://player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc"},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"iframe",w:425,h:350,url:'http://maps.google.com/maps/ms?msid=$2&output=embed"'}];e.on("ResolveName",function(e){var t;1==e.target.nodeType&&(t=e.target.getAttribute("data-mce-object"))&&(e.name=t)}),e.on("preInit",function(){var t=e.schema.getSpecialElements();tinymce.each("video audio iframe object".split(" "),function(e){t[e]=new RegExp("</"+e+"[^>]*>","gi")}),e.schema.addValidElements("object[id|style|width|height|classid|codebase|*],embed[id|style|width|height|type|src|*],video[*],audio[*]");var n=e.schema.getBoolAttrs();tinymce.each("webkitallowfullscreen mozallowfullscreen allowfullscreen".split(" "),function(e){n[e]={}}),e.parser.addNodeFilter("iframe,video,audio,object,embed",function(t,n){for(var i,a,r,o,l,s,c,u=t.length;u--;){for(a=t[u],r=new tinymce.html.Node("img",1),r.shortEnded=!0,s=a.attributes,i=s.length;i--;)o=s[i].name,l=s[i].value,"width"!==o&&"height"!==o&&"style"!==o&&(("data"==o||"src"==o)&&(l=e.convertURL(l,o)),r.attr("data-mce-p-"+o,l));c=a.firstChild&&a.firstChild.value,c&&(r.attr("data-mce-html",escape(c)),r.firstChild=null),r.attr({width:a.attr("width")||"300",height:a.attr("height")||("audio"==n?"30":"150"),style:a.attr("style"),src:tinymce.Env.transparentSrc,"data-mce-object":n,"class":"mce-object mce-object-"+n}),a.replace(r)}}),e.serializer.addAttributeFilter("data-mce-object",function(e,t){for(var n,i,a,r,o,l,s=e.length;s--;){for(n=e[s],i=new tinymce.html.Node(n.attr(t),1),"audio"!=n.attr(t)&&i.attr({width:n.attr("width"),height:n.attr("height")}),i.attr({style:n.attr("style")}),r=n.attributes,a=r.length;a--;){var c=r[a].name;0===c.indexOf("data-mce-p-")&&i.attr(c.substr(11),r[a].value)}o=n.attr("data-mce-html"),o&&(l=new tinymce.html.Node("#text",3),l.raw=!0,l.value=unescape(o),i.append(l)),n.replace(i)}})}),e.on("ObjectSelected",function(e){"audio"==e.target.getAttribute("data-mce-object")&&e.preventDefault()}),e.on("objectResized",function(e){var t,n=e.target;n.getAttribute("data-mce-object")&&(t=n.getAttribute("data-mce-html"),t&&(t=unescape(t),n.setAttribute("data-mce-html",escape(s(t,{width:e.width,height:e.height})))))}),e.addButton("media",{tooltip:"Insert/edit video",onclick:i,stateSelector:"img[data-mce-object=video]"}),e.addMenuItem("media",{icon:"media",text:"Insert video",onclick:i,context:"insert",prependToContext:!0})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/nonbreaking/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/nonbreaking/plugin.min.js new file mode 100644 index 00000000..866339c7 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/nonbreaking/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("nonbreaking",function(e){var t=e.getParam("nonbreaking_force_tab");if(e.addCommand("mceNonBreaking",function(){e.insertContent(e.plugins.visualchars&&e.plugins.visualchars.state?'<span data-mce-bogus="1" class="mce-nbsp"> </span>':" ")}),e.addButton("nonbreaking",{title:"Insert nonbreaking space",cmd:"mceNonBreaking"}),e.addMenuItem("nonbreaking",{text:"Nonbreaking space",cmd:"mceNonBreaking",context:"insert"}),t){var n=+t>1?+t:3;e.on("keydown",function(t){if(9==t.keyCode){if(t.shiftKey)return;t.preventDefault();for(var i=0;n>i;i++)e.execCommand("mceNonBreaking")}})}});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/noneditable/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/noneditable/plugin.min.js new file mode 100644 index 00000000..dd15d59e --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/noneditable/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("noneditable",function(e){function t(){function t(e){var t;if(1===e.nodeType){if(t=e.getAttribute(s),t&&"inherit"!==t)return t;if(t=e.contentEditable,"inherit"!==t)return t}return null}function n(e){for(var n;e;){if(n=t(e))return"false"===n?e:null;e=e.parentNode}}function i(e){for(;e;){if(e.id===g)return e;e=e.parentNode}}function o(e){var t;if(e)for(t=new r(e,e),e=t.current();e;e=t.next())if(3===e.nodeType)return e}function a(n,i){var o,a;return"false"===t(n)&&m.isBlock(n)?(f.select(n),void 0):(a=m.createRng(),"true"===t(n)&&(n.firstChild||n.appendChild(e.getDoc().createTextNode(" ")),n=n.firstChild,i=!0),o=m.create("span",{id:g,"data-mce-bogus":!0},p),i?n.parentNode.insertBefore(o,n):m.insertAfter(o,n),a.setStart(o.firstChild,1),a.collapse(!0),f.setRng(a),o)}function l(e){var t,n,a,r;if(e)t=f.getRng(!0),t.setStartBefore(e),t.setEndBefore(e),n=o(e),n&&n.nodeValue.charAt(0)==p&&(n=n.deleteData(0,1)),m.remove(e,!0),f.setRng(t);else for(a=i(f.getStart());(e=m.get(g))&&e!==r;)a!==e&&(n=o(e),n&&n.nodeValue.charAt(0)==p&&(n=n.deleteData(0,1)),m.remove(e,!0)),r=e}function d(){function e(e,n){var i,o,a,l,s;if(i=c.startContainer,o=c.startOffset,3==i.nodeType){if(s=i.nodeValue.length,o>0&&s>o||(n?o==s:0===o))return}else{if(!(o<i.childNodes.length))return n?null:e;var d=!n&&o>0?o-1:o;i=i.childNodes[d],i.hasChildNodes()&&(i=i.firstChild)}for(a=new r(i,e);l=a[n?"prev":"next"]();){if(3===l.nodeType&&l.nodeValue.length>0)return;if("true"===t(l))return l}return e}var i,o,s,c,d;l(),s=f.isCollapsed(),i=n(f.getStart()),o=n(f.getEnd()),(i||o)&&(c=f.getRng(!0),s?(i=i||o,(d=e(i,!0))?a(d,!0):(d=e(i,!1))?a(d,!1):f.select(i)):(c=f.getRng(!0),i&&c.setStartBefore(i),o&&c.setEndAfter(o),f.setRng(c)))}function u(o){function a(e,t){for(;e=e[t?"previousSibling":"nextSibling"];)if(3!==e.nodeType||e.nodeValue.length>0)return e}function s(e,t){f.select(e),f.collapse(t)}function u(o){function a(e){for(var t=s;t;){if(t===e)return;t=t.parentNode}m.remove(e),d()}function r(){var i,r,l=e.schema.getNonEmptyElements();for(r=new tinymce.dom.TreeWalker(s,e.getBody());(i=o?r.prev():r.next())&&!l[i.nodeName.toLowerCase()]&&!(3===i.nodeType&&tinymce.trim(i.nodeValue).length>0);)if("false"===t(i))return a(i),!0;return n(i)?!0:!1}var l,s,c,u;if(f.isCollapsed()){if(l=f.getRng(!0),s=l.startContainer,c=l.startOffset,s=i(s)||s,u=n(s))return a(u),!1;if(3==s.nodeType&&(o?c>0:c<s.nodeValue.length))return!0;if(1==s.nodeType&&(s=s.childNodes[c]||s),r())return!1}return!0}var g,p,h,y,v=o.keyCode;if(h=f.getStart(),y=f.getEnd(),g=n(h)||n(y),g&&(112>v||v>124)&&v!=c.DELETE&&v!=c.BACKSPACE){if((tinymce.isMac?o.metaKey:o.ctrlKey)&&(67==v||88==v||86==v))return;if(o.preventDefault(),v==c.LEFT||v==c.RIGHT){var b=v==c.LEFT;if(e.dom.isBlock(g)){var x=b?g.previousSibling:g.nextSibling,w=new r(x,x),C=b?w.prev():w.next();s(C,!b)}else s(g,b)}}else if(v==c.LEFT||v==c.RIGHT||v==c.BACKSPACE||v==c.DELETE){if(p=i(h)){if(v==c.LEFT||v==c.BACKSPACE)if(g=a(p,!0),g&&"false"===t(g)){if(o.preventDefault(),v!=c.LEFT)return m.remove(g),void 0;s(g,!0)}else l(p);if(v==c.RIGHT||v==c.DELETE)if(g=a(p),g&&"false"===t(g)){if(o.preventDefault(),v!=c.RIGHT)return m.remove(g),void 0;s(g,!1)}else l(p)}if((v==c.BACKSPACE||v==c.DELETE)&&!u(v==c.BACKSPACE))return o.preventDefault(),!1}}var m=e.dom,f=e.selection,g="mce_noneditablecaret",p="";e.on("mousedown",function(n){var i=e.selection.getNode();"false"===t(i)&&i==n.target&&d()}),e.on("mouseup keyup",d),e.on("keydown",u)}function n(t){var n=a.length,i=t.content,r=tinymce.trim(o);if("raw"!=t.format){for(;n--;)i=i.replace(a[n],function(t){var n=arguments,o=n[n.length-2];return o>0&&'"'==i.charAt(o-1)?t:'<span class="'+r+'" data-mce-content="'+e.dom.encode(n[0])+'">'+e.dom.encode("string"==typeof n[1]?n[1]:n[0])+"</span>"});t.content=i}}var i,o,a,r=tinymce.dom.TreeWalker,l="contenteditable",s="data-mce-"+l,c=tinymce.util.VK;i=" "+tinymce.trim(e.getParam("noneditable_editable_class","mceEditable"))+" ",o=" "+tinymce.trim(e.getParam("noneditable_noneditable_class","mceNonEditable"))+" ",a=e.getParam("noneditable_regexp"),a&&!a.length&&(a=[a]),e.on("PreInit",function(){t(),a&&e.on("BeforeSetContent",n),e.parser.addAttributeFilter("class",function(e){for(var t,n,a=e.length;a--;)n=e[a],t=" "+n.attr("class")+" ",-1!==t.indexOf(i)?n.attr(s,"true"):-1!==t.indexOf(o)&&n.attr(s,"false")}),e.serializer.addAttributeFilter(s,function(e){for(var t,n=e.length;n--;)t=e[n],a&&t.attr("data-mce-content")?(t.name="#text",t.type=3,t.raw=!0,t.value=t.attr("data-mce-content")):(t.attr(l,null),t.attr(s,null))}),e.parser.addAttributeFilter(l,function(e){for(var t,n=e.length;n--;)t=e[n],t.attr(s,t.attr(l)),t.attr(l,null)})})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/pagebreak/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/pagebreak/plugin.min.js new file mode 100644 index 00000000..8f535fa1 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/pagebreak/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("pagebreak",function(e){var t,n="mce-pagebreak",i=e.getParam("pagebreak_separator","<!-- pagebreak -->"),a='<img src="'+tinymce.Env.transparentSrc+'" class="'+n+'" data-mce-resize="false" />';t=new RegExp(i.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(e){return"\\"+e}),"gi"),e.addCommand("mcePageBreak",function(){e.execCommand("mceInsertContent",0,a)}),e.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),e.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"}),e.on("ResolveName",function(t){"IMG"==t.target.nodeName&&e.dom.hasClass(t.target,n)&&(t.name="pagebreak")}),e.on("click",function(t){t=t.target,"IMG"===t.nodeName&&e.dom.hasClass(t,n)&&e.selection.select(t)}),e.on("BeforeSetContent",function(e){e.content=e.content.replace(t,a)}),e.on("PreInit",function(){e.serializer.addNodeFilter("img",function(e){for(var t,n,a=e.length;a--;)t=e[a],n=t.attr("class"),n&&-1!==n.indexOf("mce-pagebreak")&&(t.type=3,t.value=i,t.raw=!0)})})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/paste/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/paste/plugin.min.js new file mode 100644 index 00000000..d1b15b7d --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/paste/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i<e.length;++i){if(n=s[e[i]]||o(e[i]),!n)throw"module definition dependecy not found: "+e[i];r.push(n)}t.apply(null,r)}function r(e,r,i){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(r===t)throw"invalid module definition, dependencies must be specified";if(i===t)throw"invalid module definition, definition function must be specified";n(r,function(){s[e]=i.apply(null,arguments)})}function i(e){return!!s[e]}function o(t){for(var n=e,r=t.split(/[.\/]/),i=0;i<r.length;++i){if(!n[r[i]])return;n=n[r[i]]}return n}function a(n){for(var r=0;r<n.length;r++){for(var i=e,o=n[r],a=o.split(/[.\/]/),l=0;l<a.length-1;++l)i[a[l]]===t&&(i[a[l]]={}),i=i[a[l]];i[a[a.length-1]]=s[o]}}var s={},l="tinymce/pasteplugin/Clipboard",c="tinymce/Env",d="tinymce/util/Tools",u="tinymce/util/VK",f="tinymce/pasteplugin/WordFilter",p="tinymce/html/DomParser",m="tinymce/html/Schema",h="tinymce/html/Serializer",g="tinymce/html/Node",v="tinymce/pasteplugin/Quirks",y="tinymce/pasteplugin/Plugin",b="tinymce/PluginManager";r(l,[c,d,u],function(e,t,n){function r(){return!e.gecko&&("ClipboardEvent"in window||e.webkit&&"FocusEvent"in window)}return function(i){function o(){return(new Date).getTime()}function a(e){return n.metaKeyPressed(e)&&86==e.keyCode||e.shiftKey&&45==e.keyCode}function s(e){return e.innerText||e.textContent}function l(){return o()-h<100||"text"==m.pasteFormat}function c(e,n){return t.each(n,function(t){e=t.constructor==RegExp?e.replace(t,""):e.replace(t[0],t[1])}),e}function d(t){var n=i.fire("PastePreProcess",{content:t});t=n.content,i.settings.paste_data_images||(t=t.replace(/<img src=\"data:image[^>]+>/g,"")),(i.settings.paste_remove_styles||i.settings.paste_remove_styles_if_webkit!==!1&&e.webkit)&&(t=t.replace(/ style=\"[^\"]+\"/g,"")),n.isDefaultPrevented()||i.insertContent(t)}function u(e){e=i.dom.encode(e).replace(/\r\n/g,"\n");var t=i.dom.getParent(i.selection.getStart(),i.dom.isBlock);e=t&&/^(PRE|DIV)$/.test(t.nodeName)||!i.settings.forced_root_block?c(e,[[/\n/g,"<br>"]]):c(e,[[/\n\n/g,"</p><p>"],[/^(.*<\/p>)(<p>)$/,"<p>$1"],[/\n/g,"<br />"]]);var n=i.fire("PastePreProcess",{content:e});n.isDefaultPrevented()||i.insertContent(n.content)}function f(){var e=i.dom.getViewPort().y,t=i.dom.add(i.getBody(),"div",{contentEditable:!1,"data-mce-bogus":"1",style:"position: absolute; top: "+e+"px; left: 0; width: 1px; height: 1px; overflow: hidden"},'<div contentEditable="true" data-mce-bogus="1">X</div>');return i.dom.bind(t,"beforedeactivate focusin focusout",function(e){e.stopPropagation()}),t}function p(e){i.dom.unbind(e),i.dom.remove(e)}var m=this,h;if(i.on("keydown",function(e){n.metaKeyPressed(e)&&e.shiftKey&&86==e.keyCode&&(h=o())}),r())i.on("paste",function(e){function t(e,t){for(var r=0;r<n.types.length;r++)if(n.types[r]==e)return t(n.getData(e)),!0}var n=e.clipboardData;n&&(e.preventDefault(),l()?t("text/plain",u)||t("text/html",d):t("text/html",d)||t("text/plain",u))});else{if(e.ie){var g=0;i.on("keydown",function(e){if(a(e)&&!e.isDefaultPrevented()){e.stopImmediatePropagation();var t=f();g=o(),i.dom.bind(t,"paste",function(){setTimeout(function(){i.selection.setRng(n),p(t),l()?u(s(t.firstChild)):d(t.firstChild.innerHTML)},0)});var n=i.selection.getRng();t.firstChild.focus(),t.firstChild.innerText=""}}),i.on("init",function(){var e=i.dom;i.dom.bind(i.getBody(),"paste",function(t){if(o()-g>100){var n,r=f();t.preventDefault(),e.bind(r,"paste",function(e){e.stopPropagation(),n=!0});var a=i.selection.getRng(),c=e.doc.body.createTextRange();if(c.moveToElementText(r.firstChild),c.execCommand("Paste"),p(r),!n)return i.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents."),void 0;i.selection.setRng(a),l()?u(s(r.firstChild)):d(r.firstChild.innerHTML)}})})}else i.on("init",function(){i.dom.bind(i.getBody(),"paste",function(e){e.preventDefault(),i.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.")})}),i.on("keydown",function(e){if(a(e)&&!e.isDefaultPrevented()){e.stopImmediatePropagation();var t=f(),n=i.selection.getRng();i.selection.select(t,!0),i.dom.bind(t,"paste",function(e){e.stopPropagation(),setTimeout(function(){p(t),i.lastRng=n,i.selection.setRng(n);var e=t.firstChild;e.lastChild&&"BR"==e.lastChild.nodeName&&e.removeChild(e.lastChild),l()?u(s(e)):d(e.innerHTML)},0)})}});i.settings.paste_data_images||i.on("drop",function(e){var t=e.dataTransfer;t&&t.files&&t.files.length>0&&e.preventDefault()})}i.paste_block_drop&&i.on("dragend dragover draggesture dragdrop drop drag",function(e){e.preventDefault(),e.stopPropagation()}),this.paste=d,this.pasteText=u}}),r(f,[d,p,m,h,g],function(e,t,n,r,i){return function(o){var a=e.each;o.on("PastePreProcess",function(s){function l(e){a(e,function(e){u=e.constructor==RegExp?u.replace(e,""):u.replace(e[0],e[1])})}function c(e){function t(e,t,a,s){var l=e._listLevel||o;l!=o&&(o>l?n&&(n=n.parent.parent):(r=n,n=null)),n&&n.name==a?n.append(e):(r=r||n,n=new i(a,1),s>1&&n.attr("start",""+s),e.wrap(n)),e.name="li",t.value="";var c=t.next;c&&3==c.type&&(c.value=c.value.replace(/^\u00a0+/,"")),l>o&&r.lastChild.append(n),o=l}for(var n,r,o=1,a=e.getAll("p"),s=0;s<a.length;s++)if(e=a[s],"p"==e.name&&e.firstChild){for(var l="",c=e.firstChild;c&&!(l=c.value);)c=c.firstChild;if(/^\s*[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*$/.test(l)){t(e,c,"ul");continue}if(/^\s*\w+\./.test(l)){var d=/([0-9])\./.exec(l),u=1;d&&(u=parseInt(d[1],10)),t(e,c,"ol",u);continue}n=null}}function d(t,n){if("p"===t.name){var r=/mso-list:\w+ \w+([0-9]+)/.exec(n);r&&(t._listLevel=parseInt(r[1],10))}if(o.getParam("paste_retain_style_properties","none")){var i="";if(e.each(o.dom.parseStyle(n),function(e,t){switch(t){case"horiz-align":return t="text-align",void 0;case"vert-align":return t="vertical-align",void 0;case"font-color":case"mso-foreground":return t="color",void 0;case"mso-background":case"mso-highlight":t="background"}("all"==f||p&&p[t])&&(i+=t+":"+e+";")}),i)return i}return null}var u=s.content,f,p;if(f=o.settings.paste_retain_style_properties,f&&(p=e.makeMap(f)),o.settings.paste_enable_default_filters!==!1&&/class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i.test(s.content)){s.wordContent=!0,l([/<!--[\s\S]+?-->/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,function(e,t){return t.length>0?t.replace(/./," ").slice(Math.floor(t.length/2)).split("").join("\xa0"):""}]]);var m=new n({valid_elements:"@[style],-strong/b,-em/i,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-table,-tr,-td[colspan|rowspan],-th,-thead,-tfoot,-tbody,-a[!href],sub,sup,strike"}),h=new t({},m);h.addAttributeFilter("style",function(e){for(var t=e.length,n;t--;)n=e[t],n.attr("style",d(n,n.attr("style"))),"span"!=n.name||n.attributes.length||n.unwrap()});var g=h.parse(u);c(g),s.content=new r({},m).serialize(g)}})}}),r(v,[c,d],function(e,t){return function(n){function r(e){n.on("PastePreProcess",function(t){t.content=e(t.content)})}function i(e,n){return t.each(n,function(t){e=t.constructor==RegExp?e.replace(t,""):e.replace(t[0],t[1])}),e}function o(e){return e=i(e,[/^[\s\S]*<!--StartFragment-->|<!--EndFragment-->[\s\S]*$/g,[/<span class="Apple-converted-space">\u00a0<\/span>/g,"\xa0"],/<br>$/])}function a(e){if(!s){var r=[];t.each(n.schema.getBlockElements(),function(e,t){r.push(t)}),s=new RegExp("(?:<br> [\\s\\r\\n]+|<br>)*(<\\/?("+r.join("|")+")[^>]*>)(?:<br> [\\s\\r\\n]+|<br>)*","g")}return e=i(e,[[s,"$1"]]),e=i(e,[[/<br><br>/g,"<BR><BR>"],[/<br>/g," "],[/<BR><BR>/g,"<br>"]])}var s;e.webkit&&r(o),e.ie&&r(a)}}),r(y,[b,l,f,v],function(e,t,n,r){var i;e.add("paste",function(e){var o=this,a;o.clipboard=a=new t(e),o.quirks=new r(e),o.wordFilter=new n(e),e.settings.paste_as_text&&(o.clipboard.pasteFormat="text"),e.addCommand("mceInsertClipboardContent",function(e,t){t.content&&o.clipboard.paste(t.content),t.text&&o.clipboard.pasteText(t.text)}),e.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:a.pasteFormat,onclick:function(){"text"==a.pasteFormat?(this.active(!1),a.pasteFormat="html"):(a.pasteFormat="text",this.active(!0),i||(e.windowManager.alert("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off."),i=!0))}})})}),a([l,f,v,y])}(this);
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/preview/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/preview/plugin.min.js new file mode 100644 index 00000000..b8430c64 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/preview/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("preview",function(e){var t=e.settings;e.addCommand("mcePreview",function(){e.windowManager.open({title:"Preview",width:parseInt(e.getParam("plugin_preview_width","650"),10),height:parseInt(e.getParam("plugin_preview_height","500"),10),html:'<iframe src="javascript:\'\'" frameborder="0"></iframe>',buttons:{text:"Close",onclick:function(){this.parent().parent().close()}},onPostRender:function(){var n,i=this.getEl("body").firstChild.contentWindow.document,a="";tinymce.each(e.contentCSS,function(t){a+='<link type="text/css" rel="stylesheet" href="'+e.documentBaseURI.toAbsolute(t)+'">'});var r=t.body_id||"tinymce";-1!=r.indexOf("=")&&(r=e.getParam("body_id","","hash"),r=r[e.id]||r);var o=t.body_class||"";-1!=o.indexOf("=")&&(o=e.getParam("body_class","","hash"),o=o[e.id]||""),n="<!DOCTYPE html><html><head>"+a+"</head>"+'<body id="'+r+'" class="mce-content-body '+o+'">'+e.getContent()+"</body>"+"</html>",i.open(),i.write(n),i.close()}})}),e.addButton("preview",{title:"Preview",cmd:"mcePreview"}),e.addMenuItem("preview",{text:"Preview",cmd:"mcePreview",context:"view"})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/print/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/print/plugin.min.js new file mode 100644 index 00000000..abc37b5f --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/print/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("print",function(t){t.addCommand("mcePrint",function(){t.getWin().print()}),t.addButton("print",{title:"Print",cmd:"mcePrint"}),t.addShortcut("Ctrl+P","","mcePrint"),t.addMenuItem("print",{text:"Print",cmd:"mcePrint",icon:"print",shortcut:"Ctrl+P",context:"file"})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/save/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/save/plugin.min.js new file mode 100644 index 00000000..00cb68c6 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/save/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("save",function(e){function t(){var t,n;return t=tinymce.DOM.getParent(e.id,"form"),!e.getParam("save_enablewhendirty")||e.isDirty()?(tinymce.triggerSave(),(n=e.getParam("save_onsavecallback"))?(e.execCallback("save_onsavecallback",e)&&(e.startContent=tinymce.trim(e.getContent({format:"raw"})),e.nodeChanged()),void 0):(t?(e.isNotDirty=!0,(!t.onsubmit||t.onsubmit())&&("function"==typeof t.submit?t.submit():e.windowManager.alert("Error: Form submit field collision.")),e.nodeChanged()):e.windowManager.alert("Error: No form element found."),void 0)):void 0}function n(){var t,n=tinymce.trim(e.startContent);return(t=e.getParam("save_oncancelcallback"))?(e.execCallback("save_oncancelcallback",e),void 0):(e.setContent(n),e.undoManager.clear(),e.nodeChanged(),void 0)}function i(){var t=this;e.on("nodeChange",function(){t.disabled(!e.isDirty())})}e.addCommand("mceSave",t),e.addCommand("mceCancel",n),e.addButton("save",{icon:"save",text:"Save",cmd:"mceSave",disabled:!0,onPostRender:i}),e.addButton("cancel",{text:"Cancel",icon:!1,cmd:"mceCancel",disabled:!0,onPostRender:i}),e.addShortcut("ctrl+s","","mceSave")});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/searchreplace/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/searchreplace/plugin.min.js new file mode 100644 index 00000000..56ffa92a --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/searchreplace/plugin.min.js @@ -0,0 +1 @@ +!function(){function e(e,t,n,i,a){function r(e,t){if(t=t||0,!e[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var n=e.index;if(t>0){var i=e[t];if(!i)throw"Invalid capture group";n+=e[0].indexOf(i),e[0]=i}return[n,n+e[0].length,[e[0]]]}function o(e){var t;if(3===e.nodeType)return e.data;if(f[e.nodeName])return"";if(t="",(m[e.nodeName]||g[e.nodeName])&&(t+="\n"),e=e.firstChild)do t+=o(e);while(e=e.nextSibling);return t}function l(e,t,n){var i,a,r,o,l=[],c=0,s=e,d=t.shift(),u=0;e:for(;;){if((m[s.nodeName]||g[s.nodeName])&&c++,3===s.nodeType&&(!a&&s.length+c>=d[1]?(a=s,o=d[1]-c):i&&l.push(s),!i&&s.length+c>d[0]&&(i=s,r=d[0]-c),c+=s.length),i&&a){if(s=n({startNode:i,startNodeIndex:r,endNode:a,endNodeIndex:o,innerNodes:l,match:d[2],matchIndex:u}),c-=a.length-o,i=null,a=null,l=[],d=t.shift(),u++,!d)break}else{if(!f[s.nodeName]&&s.firstChild){s=s.firstChild;continue}if(s.nextSibling){s=s.nextSibling;continue}}for(;;){if(s.nextSibling){s=s.nextSibling;break}if(s.parentNode===e)break e;s=s.parentNode}}}function c(e){var t;if("function"!=typeof e){var n=e.nodeType?e:u.createElement(e);t=function(e,t){var i=n.cloneNode(!1);return i.setAttribute("data-mce-index",t),e&&i.appendChild(u.createTextNode(e)),i}}else t=e;return function(e){var n,i,a,r=e.startNode,o=e.endNode,l=e.matchIndex;if(r===o){var c=r;a=c.parentNode,e.startNodeIndex>0&&(n=u.createTextNode(c.data.substring(0,e.startNodeIndex)),a.insertBefore(n,c));var s=t(e.match[0],l);return a.insertBefore(s,c),e.endNodeIndex<c.length&&(i=u.createTextNode(c.data.substring(e.endNodeIndex)),a.insertBefore(i,c)),c.parentNode.removeChild(c),s}n=u.createTextNode(r.data.substring(0,e.startNodeIndex)),i=u.createTextNode(o.data.substring(e.endNodeIndex));for(var d=t(r.data.substring(e.startNodeIndex),l),m=[],f=0,g=e.innerNodes.length;g>f;++f){var h=e.innerNodes[f],p=t(h.data,l);h.parentNode.replaceChild(p,h),m.push(p)}var v=t(o.data.substring(0,e.endNodeIndex),l);return a=r.parentNode,a.insertBefore(n,r),a.insertBefore(d,r),a.removeChild(r),a=o.parentNode,a.insertBefore(v,o),a.insertBefore(i,o),a.removeChild(o),v}}var s,d,u,m,f,g,h=[],p=0;if(u=t.ownerDocument,m=a.getBlockElements(),f=a.getWhiteSpaceElements(),g=a.getShortEndedElements(),d=o(t)){if(e.global)for(;s=e.exec(d);)h.push(r(s,i));else s=d.match(e),h.push(r(s,i));return h.length&&(p=h.length,l(t,h,c(n))),p}}function t(t){function n(){var e=tinymce.ui.Factory.create({type:"window",layout:"flex",pack:"center",align:"center",onClose:function(){t.focus(),o=!1,l.unmarkAllMatches()},buttons:[{text:"Find",onclick:function(){e.find("form")[0].submit()}},{text:"Replace",disabled:!0,onclick:function(){l.replace(e.find("#replace").value())||e.statusbar.items().slice(1).disabled(!0)}},{text:"Replace all",disabled:!0,onclick:function(){l.replaceAll(e.find("#replace").value()),e.statusbar.items().slice(1).disabled(!0)}},{type:"spacer",flex:1},{text:"Prev",disabled:!0,onclick:function(){l.prev()}},{text:"Next",disabled:!0,onclick:function(){l.next()}}],title:"Find and replace",items:{type:"form",padding:20,labelGap:30,spacing:10,onsubmit:function(t){var n,i,a,r,o;return t.preventDefault(),a=e.find("#case").checked(),o=e.find("#words").checked(),r=e.find("#find").value(),r.length?(r=r.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),r=o?"\\b"+r+"\\b":r,i=new RegExp(r,a?"g":"gi"),n=l.markAllMatches(i),n?l.first():tinymce.ui.MessageBox.alert("Could not find the specified string."),e.statusbar.items().slice(1).disabled(0===n),void 0):(l.unmarkAllMatches(),e.statusbar.items().slice(1).disabled(!0),void 0)},items:[{type:"textbox",name:"find",size:40,label:"Find",value:t.selection.getNode().src},{type:"textbox",name:"replace",size:40,label:"Replace with"},{type:"checkbox",name:"case",text:"Match case",label:" "},{type:"checkbox",name:"words",text:"Whole words",label:" "}]}}).renderTo().reflow();o=!0}function i(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function a(e,n){function i(){var i,o;for(i=n?t.getBody()[e?"firstChild":"lastChild"]:l[e?"endContainer":"startContainer"],o=new tinymce.dom.TreeWalker(i,t.getBody());i=o.current();){if(1==i.nodeType&&"SPAN"==i.nodeName&&null!==i.getAttribute("data-mce-index"))for(c=i.getAttribute("data-mce-index"),a=i.firstChild;i=o.current();){if(1==i.nodeType&&"SPAN"==i.nodeName&&null!==i.getAttribute("data-mce-index")){if(i.getAttribute("data-mce-index")!==c)return;r=i.firstChild}o[e?"next":"prev"]()}o[e?"next":"prev"]()}}var a,r,o=t.selection,l=o.getRng(!0),c=-1;return e=e!==!1,i(),a&&r&&(t.focus(),e?(l.setStart(a,0),l.setEnd(r,r.length)):(l.setStart(r,0),l.setEnd(a,a.length)),o.scrollIntoView(a.parentNode),o.setRng(l)),c}function r(e){e.parentNode.removeChild(e)}var o,l=this,c=-1;l.init=function(e){e.addMenuItem("searchreplace",{text:"Find and replace",shortcut:"Ctrl+F",onclick:n,separator:"before",context:"edit"}),e.addButton("searchreplace",{tooltip:"Find and replace",shortcut:"Ctrl+F",onclick:n}),e.shortcuts.add("Ctrl+F","",n)},l.markAllMatches=function(n){var i,a;return a=t.dom.create("span",{"class":"mce-match-marker","data-mce-bogus":1}),i=t.getBody(),l.unmarkAllMatches(i),e(n,i,a,!1,t.schema)},l.first=function(){return c=a(!0,!0),-1!==c},l.next=function(){return c=a(!0),-1!==c},l.prev=function(){return c=a(!1),-1!==c},l.replace=function(e,n,o){var l,s,d,u,m,f;if(-1===c&&(c=a(n)),f=a(n),d=t.getBody(),s=tinymce.toArray(d.getElementsByTagName("span")),s.length)for(l=0;l<s.length;l++){var g=s[l].getAttribute("data-mce-index");if(null!==g&&g.length&&(u=m=s[l].getAttribute("data-mce-index"),o||u===c))for(e.length?(s[l].firstChild.nodeValue=e,i(s[l])):r(s[l]);s[++l];)if(u=s[l].getAttribute("data-mce-index"),null!==g&&g.length){if(u!==m){l--;break}r(s[l])}}return-1==f&&(f=a(n,!0)),c=f,o&&t.selection.setCursorLocation(t.getBody(),0),t.undoManager.add(),-1!==c},l.replaceAll=function(e){l.replace(e,!0,!0)},l.unmarkAllMatches=function(){var e,n,a;for(a=t.getBody(),n=a.getElementsByTagName("span"),e=n.length;e--;)a=n[e],a.getAttribute("data-mce-index")&&i(a)},t.on("beforeaddundo keydown",function(e){return o?(e.preventDefault(),!1):void 0})}tinymce.PluginManager.add("searchreplace",t)}();
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/spellchecker/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/spellchecker/plugin.min.js new file mode 100644 index 00000000..9cbf0315 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/spellchecker/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],o=0;o<e.length;++o){if(n=s[e[o]]||i(e[o]),!n)throw"module definition dependecy not found: "+e[o];r.push(n)}t.apply(null,r)}function r(e,r,o){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(r===t)throw"invalid module definition, dependencies must be specified";if(o===t)throw"invalid module definition, definition function must be specified";n(r,function(){s[e]=o.apply(null,arguments)})}function o(e){return!!s[e]}function i(t){for(var n=e,r=t.split(/[.\/]/),o=0;o<r.length;++o){if(!n[r[o]])return;n=n[r[o]]}return n}function a(n){for(var r=0;r<n.length;r++){for(var o=e,i=n[r],a=i.split(/[.\/]/),l=0;l<a.length-1;++l)o[a[l]]===t&&(o[a[l]]={}),o=o[a[l]];o[a[a.length-1]]=s[i]}}var s={},l="tinymce/spellcheckerplugin/DomTextMatcher",c="tinymce/spellcheckerplugin/Plugin",d="tinymce/PluginManager",u="tinymce/util/Tools",f="tinymce/ui/Menu",p="tinymce/dom/DOMUtils",m="tinymce/util/JSONRequest",h="tinymce/util/URI";r(l,[],function(){return function(e,t,n){function r(e){if(!e[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var t=e.index;return[t,t+e[0].length,[e[0]]]}function o(e){var t;if(3===e.nodeType)return e.data;if(g[e.nodeName])return"";if(t="",(h[e.nodeName]||v[e.nodeName])&&(t+="\n"),e=e.firstChild)do t+=o(e);while(e=e.nextSibling);return t}function i(e,t,n){var r,o,i,a,s=[],l=0,c=e,d=t.shift(),u=0;e:for(;;){if((h[c.nodeName]||v[c.nodeName])&&l++,3===c.nodeType&&(!o&&c.length+l>=d[1]?(o=c,a=d[1]-l):r&&s.push(c),!r&&c.length+l>d[0]&&(r=c,i=d[0]-l),l+=c.length),r&&o){if(c=n({startNode:r,startNodeIndex:i,endNode:o,endNodeIndex:a,innerNodes:s,match:d[2],matchIndex:u}),l-=o.length-a,r=null,o=null,s=[],d=t.shift(),u++,!d)break}else{if(!g[c.nodeName]&&c.firstChild){c=c.firstChild;continue}if(c.nextSibling){c=c.nextSibling;continue}}for(;;){if(c.nextSibling){c=c.nextSibling;break}if(c.parentNode===e)break e;c=c.parentNode}}}function a(e){var t;if("function"!=typeof e){var n=e.nodeType?e:m.createElement(e);t=function(e,t){var r=n.cloneNode(!1);return r.setAttribute("data-mce-index",t),e&&r.appendChild(m.createTextNode(e)),r}}else t=e;return function r(e){var n,r,o,i=e.startNode,a=e.endNode,s=e.matchIndex;if(i===a){var l=i;o=l.parentNode,e.startNodeIndex>0&&(n=m.createTextNode(l.data.substring(0,e.startNodeIndex)),o.insertBefore(n,l));var c=t(e.match[0],s);return o.insertBefore(c,l),e.endNodeIndex<l.length&&(r=m.createTextNode(l.data.substring(e.endNodeIndex)),o.insertBefore(r,l)),l.parentNode.removeChild(l),c}n=m.createTextNode(i.data.substring(0,e.startNodeIndex)),r=m.createTextNode(a.data.substring(e.endNodeIndex));for(var d=t(i.data.substring(e.startNodeIndex),s),u=[],f=0,p=e.innerNodes.length;p>f;++f){var h=e.innerNodes[f],g=t(h.data,s);h.parentNode.replaceChild(g,h),u.push(g)}var v=t(a.data.substring(0,e.endNodeIndex),s);return o=i.parentNode,o.insertBefore(n,i),o.insertBefore(d,i),o.removeChild(i),o=a.parentNode,o.insertBefore(v,a),o.insertBefore(r,a),o.removeChild(a),v}}function s(e){var t=[];return l(function(n,r){e(n,r)&&t.push(n)}),u=t,this}function l(e){for(var t=0,n=u.length;n>t&&e(u[t],t)!==!1;t++);return this}function c(e){return u.length&&(p=u.length,i(t,u,a(e))),this}var d,u=[],f,p=0,m,h,g,v;if(m=t.ownerDocument,h=n.getBlockElements(),g=n.getWhiteSpaceElements(),v=n.getShortEndedElements(),f=o(t),f&&e.global)for(;d=e.exec(f);)u.push(r(d));return{text:f,count:p,matches:u,each:l,filter:s,mark:c}}}),r(c,[l,d,u,f,p,m,h],function(e,t,n,r,o,i,a){t.add("spellchecker",function(t,s){function l(e){for(var t in e)return!1;return!0}function c(e,i){var a=[],s=g[i];n.each(s,function(e){a.push({text:e,onclick:function(){t.insertContent(e),u()}})}),a.push.apply(a,[{text:"-"},{text:"Ignore",onclick:function(){p(e,i)}},{text:"Ignore all",onclick:function(){p(e,i,!0)}},{text:"Finish",onclick:m}]),y=new r({items:a,context:"contextmenu",onautohide:function(e){-1!=e.target.className.indexOf("spellchecker")&&e.preventDefault()},onhide:function(){y.remove(),y=null}}),y.renderTo(document.body);var l=o.DOM.getPos(t.getContentAreaContainer()),c=t.dom.getPos(e);l.x+=c.x,l.y+=c.y,y.moveTo(l.x,l.y+e.offsetHeight)}function d(){function n(e){return t.setProgressState(!1),l(e)?(t.windowManager.alert("No misspellings found"),v=!1,void 0):(g=e,o.filter(function(t){return!!e[t[2][0]]}).mark(t.dom.create("span",{"class":"mce-spellchecker-word","data-mce-bogus":1})),o=null,t.fire("SpellcheckStart"),void 0)}function r(e,n,r){i.sendRPC({url:new a(s).toAbsolute(b.spellchecker_rpc_url),method:e,params:{lang:b.spellchecker_language||"en",words:n},success:function(e){r(e)},error:function(e,n){e="JSON Parse error."==e?"Non JSON response:"+n.responseText:"Error: "+e,t.windowManager.alert(e),t.setProgressState(!1),o=null,v=!1}})}var o,c=[],d={};if(v)return m(),void 0;v=!0;var u=t.getParam("spellchecker_wordchar_pattern")||new RegExp('[^\\s!"#$%&()*+,-./:;<=>?@[\\]^_{|}`\xa7\xa9\xab\xae\xb1\xb6\xb7\xb8\xbb\xbc\xbd\xbe\xbf\xd7\xf7\xa4\u201d\u201c\u201e]+',"g");o=new e(u,t.getBody(),t.schema).each(function(e){var t=e[2][0];if(!d[t]){if(/^\d+$/.test(t)||1==t.length)return;c.push(t),d[t]=!0}}),t.setProgressState(!0);var f=b.spellchecker_callback||r;f("spellcheck",c,n)}function u(){t.dom.select("span.mce-spellchecker-word").length||m()}function f(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function p(e,r,o){o?n.each(t.dom.select("span.mce-spellchecker-word"),function(e){var t=e.innerText||e.textContent;t==r&&f(e)}):f(e),u()}function m(){var e,n,r;for(v=!1,r=t.getBody(),n=r.getElementsByTagName("span"),e=n.length;e--;)r=n[e],r.getAttribute("data-mce-index")&&f(r);t.fire("SpellcheckEnd")}function h(e){var n,r,o,i=-1,a,s;for(e=""+e,n=t.getBody().getElementsByTagName("span"),r=0;r<n.length&&(o=n[r],"mce-spellchecker-word"!=o.className||(i=o.getAttribute("data-mce-index"),i===e&&(i=e,a||(a=o.firstChild),s=o.firstChild),i===e||!s));r++);var l=t.dom.createRng();return l.setStart(a,0),l.setEnd(s,s.length),t.selection.setRng(l),l}var g,v,y,b=t.settings;t.on("click",function(e){if("mce-spellchecker-word"==e.target.className){e.preventDefault();var t=h(e.target.getAttribute("data-mce-index"));c(e.target,t.toString())}}),t.addMenuItem("spellchecker",{text:"Spellcheck",context:"tools",onclick:d,selectable:!0,onPostRender:function(){var e=this;t.on("SpellcheckStart SpellcheckEnd",function(){e.active(v)})}}),t.addButton("spellchecker",{tooltip:"Spellcheck",onclick:d,onPostRender:function(){var e=this;t.on("SpellcheckStart SpellcheckEnd",function(){e.active(v)})}}),t.on("remove",function(){y&&(y.remove(),y=null)})})}),a([l,c])}(this);
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js new file mode 100644 index 00000000..bd71785a --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("tabfocus",function(e){function n(e){9===e.keyCode&&e.preventDefault()}function t(n){function t(n){function t(e){return"BODY"===e.nodeName||"hidden"!=e.type&&"none"!=e.style.display&&"hidden"!=e.style.visibility&&t(e.parentNode)}function r(e){return e.tabIndex||"INPUT"==e.nodeName||"TEXTAREA"==e.nodeName}function a(e){return!r(e)&&"-1"!=e.getAttribute("tabindex")&&t(e)}if(d=i.select(":input:enabled,*[tabindex]:not(iframe)"),o(d,function(n,t){return n.id==e.id?(u=t,!1):void 0}),n>0){for(c=u+1;c<d.length;c++)if(a(d[c]))return d[c]}else for(c=u-1;c>=0;c--)if(a(d[c]))return d[c];return null}var u,d,a,c;if(9===n.keyCode&&(a=r(e.getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next"))),1==a.length&&(a[1]=a[0],a[0]=":prev"),d=n.shiftKey?":prev"==a[0]?t(-1):i.get(a[0]):":next"==a[1]?t(1):i.get(a[1]))){var f=tinymce.get(d.id||d.name);d.id&&f?f.focus():window.setTimeout(function(){tinymce.Env.webkit||window.focus(),d.focus()},10),n.preventDefault()}}var i=tinymce.DOM,o=tinymce.each,r=tinymce.explode;e.on("init",function(){e.inline&&tinymce.DOM.setAttrib(e.getBody(),"tabIndex",null)}),e.on("keyup",n),tinymce.Env.gecko?e.on("keypress keydown",t):e.on("keydown",t)});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/table/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/table/plugin.min.js new file mode 100644 index 00000000..c7c2e8ed --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/table/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i<e.length;++i){if(n=s[e[i]]||o(e[i]),!n)throw"module definition dependecy not found: "+e[i];r.push(n)}t.apply(null,r)}function r(e,r,i){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(r===t)throw"invalid module definition, dependencies must be specified";if(i===t)throw"invalid module definition, definition function must be specified";n(r,function(){s[e]=i.apply(null,arguments)})}function i(e){return!!s[e]}function o(t){for(var n=e,r=t.split(/[.\/]/),i=0;i<r.length;++i){if(!n[r[i]])return;n=n[r[i]]}return n}function a(n){for(var r=0;r<n.length;r++){for(var i=e,o=n[r],a=o.split(/[.\/]/),l=0;l<a.length-1;++l)i[a[l]]===t&&(i[a[l]]={}),i=i[a[l]];i[a[a.length-1]]=s[o]}}var s={},l="tinymce/tableplugin/TableGrid",c="tinymce/util/Tools",d="tinymce/Env",u="tinymce/tableplugin/Quirks",f="tinymce/util/VK",p="tinymce/tableplugin/CellSelection",m="tinymce/dom/TreeWalker",h="tinymce/tableplugin/Plugin",g="tinymce/PluginManager";r(l,[c,d],function(e,t){function n(e,t){return parseInt(e.getAttribute(t)||1,10)}var r=e.each;return function(i,o){function a(){var e=0;R=[],r(["thead","tbody","tfoot"],function(t){var i=H.select("> "+t+" tr",o);r(i,function(i,o){o+=e,r(H.select("> td, > th",i),function(e,r){var i,a,s,l;if(R[o])for(;R[o][r];)r++;for(s=n(e,"rowspan"),l=n(e,"colspan"),a=o;o+s>a;a++)for(R[a]||(R[a]=[]),i=r;r+l>i;i++)R[a][i]={part:t,real:a==o&&i==r,elm:e,rowspan:s,colspan:l}})}),e+=i.length})}function s(e,t){return e=e.cloneNode(t),e.removeAttribute("id"),e}function l(e,t){var n;return n=R[t],n?n[e]:void 0}function c(e,t,n){e&&(n=parseInt(n,10),1===n?e.removeAttribute(t,1):e.setAttribute(t,n,1))}function d(e){return e&&(H.hasClass(e.elm,"mce-item-selected")||e==P)}function u(){var e=[];return r(o.rows,function(t){r(t.cells,function(n){return H.hasClass(n,"mce-item-selected")||n==P.elm?(e.push(t),!1):void 0})}),e}function f(){var e=H.createRng();e.setStartAfter(o),e.setEndAfter(o),M.setRng(e),H.remove(o)}function p(n){var o,a={};return i.settings.table_clone_elements!==!1&&(a=e.makeMap((i.settings.table_clone_elements||"strong em b i span font h1 h2 h3 h4 h5 h6 p div").toUpperCase(),/[ ,]/)),e.walk(n,function(e){var i;return 3==e.nodeType?(r(H.getParents(e.parentNode,null,n).reverse(),function(e){a[e.nodeName]&&(e=s(e,!1),o?i&&i.appendChild(e):o=i=e,i=e)}),i&&(i.innerHTML=t.ie?" ":'<br data-mce-bogus="1" />'),!1):void 0},"childNodes"),n=s(n,!1),c(n,"rowSpan",1),c(n,"colSpan",1),o?n.appendChild(o):t.ie||(n.innerHTML='<br data-mce-bogus="1" />'),n}function m(){var e=H.createRng(),t;return r(H.select("tr",o),function(e){0===e.cells.length&&H.remove(e)}),0===H.select("tr",o).length?(e.setStartBefore(o),e.setEndBefore(o),M.setRng(e),H.remove(o),void 0):(r(H.select("thead,tbody,tfoot",o),function(e){0===e.rows.length&&H.remove(e)}),a(),t=R[Math.min(R.length-1,A.y)],t&&(M.select(t[Math.min(t.length-1,A.x)].elm,!0),M.collapse(!0)),void 0)}function h(e,t,n,r){var i,o,a,s,l;for(i=R[t][e].elm.parentNode,a=1;n>=a;a++)if(i=H.getNext(i,"tr")){for(o=e;o>=0;o--)if(l=R[t+a][o].elm,l.parentNode==i){for(s=1;r>=s;s++)H.insertAfter(p(l),l);break}if(-1==o)for(s=1;r>=s;s++)i.insertBefore(p(i.cells[0]),i.cells[0])}}function g(){r(R,function(e,t){r(e,function(e,r){var i,o,a;if(d(e)&&(e=e.elm,i=n(e,"colspan"),o=n(e,"rowspan"),i>1||o>1)){for(c(e,"rowSpan",1),c(e,"colSpan",1),a=0;i-1>a;a++)H.insertAfter(p(e),e);h(r,t,o-1,i)}})})}function v(t,n,i){var o,s,u,f,p,h,v,y,b,C,x;if(t?(o=S(t),s=o.x,u=o.y,f=s+(n-1),p=u+(i-1)):(A=B=null,r(R,function(e,t){r(e,function(e,n){d(e)&&(A||(A={x:n,y:t}),B={x:n,y:t})})}),s=A.x,u=A.y,f=B.x,p=B.y),y=l(s,u),b=l(f,p),y&&b&&y.part==b.part){for(g(),a(),y=l(s,u).elm,c(y,"colSpan",f-s+1),c(y,"rowSpan",p-u+1),v=u;p>=v;v++)for(h=s;f>=h;h++)R[v]&&R[v][h]&&(t=R[v][h].elm,t!=y&&(C=e.grep(t.childNodes),r(C,function(e){y.appendChild(e)}),C.length&&(C=e.grep(y.childNodes),x=0,r(C,function(e){"BR"==e.nodeName&&H.getAttrib(e,"data-mce-bogus")&&x++<C.length-1&&y.removeChild(e)})),H.remove(t)));m()}}function y(e){var t,i,o,a,l,u,f,m,h;for(r(R,function(n,i){return r(n,function(n){return d(n)&&(n=n.elm,l=n.parentNode,u=s(l,!1),t=i,e)?!1:void 0}),e?!t:void 0}),a=0;a<R[0].length;a++)if(R[t][a]&&(i=R[t][a].elm,i!=o)){if(e){if(t>0&&R[t-1][a]&&(m=R[t-1][a].elm,h=n(m,"rowSpan"),h>1)){c(m,"rowSpan",h+1);continue}}else if(h=n(i,"rowspan"),h>1){c(i,"rowSpan",h+1);continue}f=p(i),c(f,"colSpan",i.colSpan),u.appendChild(f),o=i}u.hasChildNodes()&&(e?l.parentNode.insertBefore(u,l):H.insertAfter(u,l))}function b(e){var t,i;r(R,function(n){return r(n,function(n,r){return d(n)&&(t=r,e)?!1:void 0}),e?!t:void 0}),r(R,function(r,o){var a,s,l;r[t]&&(a=r[t].elm,a!=i&&(l=n(a,"colspan"),s=n(a,"rowspan"),1==l?e?(a.parentNode.insertBefore(p(a),a),h(t,o,s-1,l)):(H.insertAfter(p(a),a),h(t,o,s-1,l)):c(a,"colSpan",a.colSpan+1),i=a))})}function C(){var t=[];r(R,function(i){r(i,function(i,o){d(i)&&-1===e.inArray(t,o)&&(r(R,function(e){var t=e[o].elm,r;r=n(t,"colSpan"),r>1?c(t,"colSpan",r-1):H.remove(t)}),t.push(o))})}),m()}function x(){function e(e){var t,i,o;t=H.getNext(e,"tr"),r(e.cells,function(e){var t=n(e,"rowSpan");t>1&&(c(e,"rowSpan",t-1),i=S(e),h(i.x,i.y,1,1))}),i=S(e.cells[0]),r(R[i.y],function(e){var t;e=e.elm,e!=o&&(t=n(e,"rowSpan"),1>=t?H.remove(e):c(e,"rowSpan",t-1),o=e)})}var t;t=u(),r(t.reverse(),function(t){e(t)}),m()}function w(){var e=u();return H.remove(e),m(),e}function _(){var e=u();return r(e,function(t,n){e[n]=s(t,!0)}),e}function N(e,t){var n=u(),i=n[t?0:n.length-1],o=i.cells.length;e&&(r(R,function(e){var t;return o=0,r(e,function(e){e.real&&(o+=e.colspan),e.elm.parentNode==i&&(t=1)}),t?!1:void 0}),t||e.reverse(),r(e,function(e){var n,r=e.cells.length,a;for(n=0;r>n;n++)a=e.cells[n],c(a,"colSpan",1),c(a,"rowSpan",1);for(n=r;o>n;n++)e.appendChild(p(e.cells[r-1]));for(n=o;r>n;n++)H.remove(e.cells[n]);t?i.parentNode.insertBefore(e,i):H.insertAfter(e,i)}),H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"))}function S(e){var t;return r(R,function(n,i){return r(n,function(n,r){return n.elm==e?(t={x:r,y:i},!1):void 0}),!t}),t}function E(e){A=S(e)}function k(){var e,t;return e=t=0,r(R,function(n,i){r(n,function(n,r){var o,a;d(n)&&(n=R[i][r],r>e&&(e=r),i>t&&(t=i),n.real&&(o=n.colspan-1,a=n.rowspan-1,o&&r+o>e&&(e=r+o),a&&i+a>t&&(t=i+a)))})}),{x:e,y:t}}function T(e){var t,n,r,i,o,a,s,l,c,d;if(B=S(e),A&&B){for(t=Math.min(A.x,B.x),n=Math.min(A.y,B.y),r=Math.max(A.x,B.x),i=Math.max(A.y,B.y),o=r,a=i,d=n;a>=d;d++)e=R[d][t],e.real||t-(e.colspan-1)<t&&(t-=e.colspan-1);for(c=t;o>=c;c++)e=R[n][c],e.real||n-(e.rowspan-1)<n&&(n-=e.rowspan-1);for(d=n;i>=d;d++)for(c=t;r>=c;c++)e=R[d][c],e.real&&(s=e.colspan-1,l=e.rowspan-1,s&&c+s>o&&(o=c+s),l&&d+l>a&&(a=d+l));for(H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=n;a>=d;d++)for(c=t;o>=c;c++)R[d][c]&&H.addClass(R[d][c].elm,"mce-item-selected")}}var R,A,B,P,M=i.selection,H=M.dom;o=o||H.getParent(M.getStart(),"table"),a(),P=H.getParent(M.getStart(),"th,td"),P&&(A=S(P),B=k(),P=l(A.x,A.y)),e.extend(this,{deleteTable:f,split:g,merge:v,insertRow:y,insertCol:b,deleteCols:C,deleteRows:x,cutRows:w,copyRows:_,pasteRows:N,getPos:S,setStartCell:E,setEndCell:T})}}),r(u,[f,d,c],function(e,t,n){function r(e,t){return parseInt(e.getAttribute(t)||1,10)}var i=n.each;return function(n){function o(){function t(t){function o(e,r){var i=e?"previousSibling":"nextSibling",o=n.dom.getParent(r,"tr"),s=o[i];if(s)return g(n,r,s,e),t.preventDefault(),!0;var d=n.dom.getParent(o,"table"),u=o.parentNode,f=u.nodeName.toLowerCase();if("tbody"===f||f===(e?"tfoot":"thead")){var p=a(e,d,u,"tbody");if(null!==p)return l(e,p,r)}return c(e,o,i,d)}function a(e,t,r,i){var o=n.dom.select(">"+i,t),a=o.indexOf(r);if(e&&0===a||!e&&a===o.length-1)return s(e,t);if(-1===a){var l="thead"===r.tagName.toLowerCase()?0:o.length-1;return o[l]}return o[a+(e?-1:1)]}function s(e,t){var r=e?"thead":"tfoot",i=n.dom.select(">"+r,t);return 0!==i.length?i[0]:null}function l(e,r,i){var o=d(r,e);return o&&g(n,i,o,e),t.preventDefault(),!0}function c(e,r,i,a){var s=a[i];if(s)return u(s),!0;var l=n.dom.getParent(a,"td,th");if(l)return o(e,l,t);var c=d(r,!e);return u(c),t.preventDefault(),!1}function d(e,t){var r=e&&e[t?"lastChild":"firstChild"];return r&&"BR"===r.nodeName?n.dom.getParent(r,"td,th"):r}function u(e){n.selection.setCursorLocation(e,0)}function f(){return b==e.UP||b==e.DOWN}function p(e){var t=e.selection.getNode(),n=e.dom.getParent(t,"tr");return null!==n}function m(e){for(var t=0,n=e;n.previousSibling;)n=n.previousSibling,t+=r(n,"colspan");return t}function h(e,t){var n=0,o=0;return i(e.children,function(e,i){return n+=r(e,"colspan"),o=i,n>t?!1:void 0}),o}function g(e,t,r,i){var o=m(n.dom.getParent(t,"td,th")),a=h(r,o),s=r.childNodes[a],l=d(s,i);u(l||s)}function v(e){var t=n.selection.getNode(),r=n.dom.getParent(t,"td,th"),i=n.dom.getParent(e,"td,th");return r&&r!==i&&y(r,i)}function y(e,t){return n.dom.getParent(e,"TABLE")===n.dom.getParent(t,"TABLE")}var b=t.keyCode;if(f()&&p(n)){var C=n.selection.getNode();setTimeout(function(){v(C)&&o(!t.shiftKey&&b===e.UP,C,t)},0)}}n.on("KeyDown",function(e){t(e)})}function a(){function e(e,t){var n=t.ownerDocument,r=n.createRange(),i;return r.setStartBefore(t),r.setEnd(e.endContainer,e.endOffset),i=n.createElement("body"),i.appendChild(r.cloneContents()),0===i.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}n.on("KeyDown",function(t){var r,i,o=n.dom;(37==t.keyCode||38==t.keyCode)&&(r=n.selection.getRng(),i=o.getParent(r.startContainer,"table"),i&&n.getBody().firstChild==i&&e(r,i)&&(r=o.createRng(),r.setStartBefore(i),r.setEndBefore(i),n.selection.setRng(r),t.preventDefault()))})}function s(){n.on("KeyDown SetContent VisualAid",function(){var e;for(e=n.getBody().lastChild;e;e=e.previousSibling)if(3==e.nodeType){if(e.nodeValue.length>0)break}else if(1==e.nodeType&&!e.getAttribute("data-mce-bogus"))break;e&&"TABLE"==e.nodeName&&(n.settings.forced_root_block?n.dom.add(n.getBody(),n.settings.forced_root_block,null,t.ie?" ":'<br data-mce-bogus="1" />'):n.dom.add(n.getBody(),"br",{"data-mce-bogus":"1"}))}),n.on("PreProcess",function(e){var t=e.node.lastChild;t&&("BR"==t.nodeName||1==t.childNodes.length&&("BR"==t.firstChild.nodeName||"\xa0"==t.firstChild.nodeValue))&&t.previousSibling&&"TABLE"==t.previousSibling.nodeName&&n.dom.remove(t)})}function l(){function e(e,t,n,r){var i=3,o=e.dom.getParent(t.startContainer,"TABLE"),a,s,l;return o&&(a=o.parentNode),s=t.startContainer.nodeType==i&&0===t.startOffset&&0===t.endOffset&&r&&("TR"==n.nodeName||n==a),l=("TD"==n.nodeName||"TH"==n.nodeName)&&!r,s||l}function t(){var t=n.selection.getRng(),r=n.selection.getNode(),i=n.dom.getParent(t.startContainer,"TD,TH");if(e(n,t,r,i)){i||(i=r);for(var o=i.lastChild;o.lastChild;)o=o.lastChild;t.setEnd(o,o.nodeValue.length),n.selection.setRng(t)}}n.on("KeyDown",function(){t()}),n.on("MouseDown",function(e){2!=e.button&&t()})}t.webkit&&(o(),l()),t.gecko&&(a(),s())}}),r(p,[l,m,c],function(e,t,n){return function(r){function i(){r.getBody().style.webkitUserSelect="",c&&(r.dom.removeClass(r.dom.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),c=!1)}var o=r.dom,a,s,l,c=!0;return r.on("MouseDown",function(e){2!=e.button&&(i(),s=o.getParent(e.target,"td,th"),l=o.getParent(s,"table"))}),o.bind(r.getDoc(),"mouseover",function(t){var n,i,d=t.target;if(s&&(a||d!=s)&&("TD"==d.nodeName||"TH"==d.nodeName)){i=o.getParent(d,"table"),i==l&&(a||(a=new e(r,i),a.setStartCell(s),r.getBody().style.webkitUserSelect="none"),a.setEndCell(d),c=!0),n=r.selection.getSel();try{n.removeAllRanges?n.removeAllRanges():n.empty()}catch(u){}t.preventDefault()}}),r.on("MouseUp",function(){function e(e,r){var o=new t(e,e);do{if(3==e.nodeType&&0!==n.trim(e.nodeValue).length)return r?i.setStart(e,0):i.setEnd(e,e.nodeValue.length),void 0;if("BR"==e.nodeName)return r?i.setStartBefore(e):i.setEndBefore(e),void 0}while(e=r?o.next():o.prev())}var i,c=r.selection,d,u,f,p,m;if(s){if(a&&(r.getBody().style.webkitUserSelect=""),d=o.select("td.mce-item-selected,th.mce-item-selected"),d.length>0){i=o.createRng(),f=d[0],m=d[d.length-1],i.setStartBefore(f),i.setEndAfter(f),e(f,1),u=new t(f,o.getParent(d[0],"table"));do if("TD"==f.nodeName||"TH"==f.nodeName){if(!o.hasClass(f,"mce-item-selected"))break;p=f}while(f=u.next());e(p),c.setRng(i)}r.nodeChanged(),s=a=l=null}}),r.on("KeyUp",function(){i()}),{clear:i}}}),r(h,[l,u,p,c,m,d,g],function(e,t,n,r,i,o,a){function s(r){function i(e){return e?e.replace(/px$/,""):""}function a(e){return/^[0-9]+$/.test(e)&&(e+="px"),e}function s(e){l("left center right".split(" "),function(t){r.formatter.remove("align"+t,{},e)})}function c(){var e=r.dom,t,n,c;t=r.dom.getParent(r.selection.getStart(),"table"),c=!1,n={width:i(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:i(e.getStyle(t,"height")||e.getAttrib(t,"height")),cellspacing:e.getAttrib(t,"cellspacing"),cellpadding:e.getAttrib(t,"cellpadding"),border:e.getAttrib(t,"border"),caption:!!e.select("caption",t)[0]},l("left center right".split(" "),function(e){r.formatter.matchNode(t,"align"+e)&&(n.align=e)}),r.windowManager.open({title:"Table properties",items:{type:"form",layout:"grid",columns:2,data:n,defaults:{type:"textbox",maxWidth:50},items:[c?{label:"Cols",name:"cols",disabled:!0}:null,c?{label:"Rows",name:"rows",disabled:!0}:null,{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell spacing",name:"cellspacing"},{label:"Cell padding",name:"cellpadding"},{label:"Border",name:"border"},{label:"Caption",name:"caption",type:"checkbox"},{label:"Alignment",minWidth:90,name:"align",type:"listbox",text:"None",maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]}]},onsubmit:function(){var n=this.toJSON(),i;r.undoManager.transact(function(){r.dom.setAttribs(t,{cellspacing:n.cellspacing,cellpadding:n.cellpadding,border:n.border}),r.dom.setStyles(t,{width:a(n.width),height:a(n.height)}),i=e.select("caption",t)[0],i&&!n.caption&&e.remove(i),!i&&n.caption&&(i=e.create("caption"),o.ie||(i.innerHTML='<br data-mce-bogus="1"/>'),t.insertBefore(i,t.firstChild)),s(t),n.align&&r.formatter.apply("align"+n.align,{},t),r.focus(),r.addVisual()})}})}function d(e,t){r.windowManager.open({title:"Merge cells",body:[{label:"Cols",name:"cols",type:"textbox",size:10},{label:"Rows",name:"rows",type:"textbox",size:10}],onsubmit:function(){var n=this.toJSON();r.undoManager.transact(function(){e.merge(t,n.cols,n.rows)})}})}function u(){var e=r.dom,t,n,o=[];o=r.dom.select("td.mce-item-selected,th.mce-item-selected"),t=r.dom.getParent(r.selection.getStart(),"td,th"),!o.length&&t&&o.push(t),t=t||o[0],n={width:i(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:i(e.getStyle(t,"height")||e.getAttrib(t,"height")),scope:e.getAttrib(t,"scope")},n.type=t.nodeName.toLowerCase(),l("left center right".split(" "),function(e){r.formatter.matchNode(t,"align"+e)&&(n.align=e)}),r.windowManager.open({title:"Cell properties",items:{type:"form",data:n,layout:"grid",columns:2,defaults:{type:"textbox",maxWidth:50},items:[{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell type",name:"type",type:"listbox",text:"None",minWidth:90,maxWidth:null,menu:[{text:"Cell",value:"td"},{text:"Header cell",value:"th"}]},{label:"Scope",name:"scope",type:"listbox",text:"None",minWidth:90,maxWidth:null,menu:[{text:"None",value:""},{text:"Row",value:"row"},{text:"Column",value:"col"},{text:"Row group",value:"rowgroup"},{text:"Column group",value:"colgroup"}]},{label:"Alignment",name:"align",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]}]},onsubmit:function(){var t=this.toJSON();r.undoManager.transact(function(){l(o,function(n){r.dom.setAttrib(n,"scope",t.scope),r.dom.setStyles(n,{width:a(t.width),height:a(t.height)}),t.type&&n.nodeName.toLowerCase()!=t.type&&(n=e.rename(n,t.type)),s(n),t.align&&r.formatter.apply("align"+t.align,{},n)}),r.focus()})}})}function f(){var e=r.dom,t,n,o,c,d=[];t=r.dom.getParent(r.selection.getStart(),"table"),n=r.dom.getParent(r.selection.getStart(),"td,th"),l(t.rows,function(t){l(t.cells,function(r){return e.hasClass(r,"mce-item-selected")||r==n?(d.push(t),!1):void 0})}),o=d[0],c={height:i(e.getStyle(o,"height")||e.getAttrib(o,"height")),scope:e.getAttrib(o,"scope")},c.type=o.parentNode.nodeName.toLowerCase(),l("left center right".split(" "),function(e){r.formatter.matchNode(o,"align"+e)&&(c.align=e)}),r.windowManager.open({title:"Row properties",items:{type:"form",data:c,columns:2,defaults:{type:"textbox"},items:[{type:"listbox",name:"type",label:"Row type",text:"None",maxWidth:null,menu:[{text:"Header",value:"thead"},{text:"Body",value:"tbody"},{text:"Footer",value:"tfoot"}]},{type:"listbox",name:"align",label:"Alignment",text:"None",maxWidth:null,menu:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"Height",name:"height"}]},onsubmit:function(){var t=this.toJSON(),n,i,o;r.undoManager.transact(function(){var c=t.type;l(d,function(l){r.dom.setAttrib(l,"scope",t.scope),r.dom.setStyles(l,{height:a(t.height)}),c!=l.parentNode.nodeName.toLowerCase()&&(n=e.getParent(l,"table"),i=l.parentNode,o=e.select(c,n)[0],o||(o=e.create(c),n.firstChild?n.insertBefore(o,n.firstChild):n.appendChild(o)),o.appendChild(l),i.hasChildNodes()||e.remove(i)),s(l),t.align&&r.formatter.apply("align"+t.align,{},l)}),r.focus()})}})}function p(e){return function(){r.execCommand(e)}}function m(e,t){var n,i,a;for(a="<table><tbody>",n=0;t>n;n++){for(a+="<tr>",i=0;e>i;i++)a+="<td>"+(o.ie?" ":"<br>")+"</td>";a+="</tr>"}a+="</tbody></table>",r.insertContent(a)}function h(e,t){function n(){e.disabled(!r.dom.getParent(r.selection.getStart(),t)),r.selection.selectorChanged(t,function(t){e.disabled(!t)})}r.initialized?n():r.on("init",n)}function g(){h(this,"table")}function v(){h(this,"td,th")}function y(){var e="";e='<table role="presentation" class="mce-grid mce-grid-border">';for(var t=0;10>t;t++){e+="<tr>";for(var n=0;10>n;n++)e+='<td><a href="#" data-mce-index="'+n+","+t+'"></a></td>';e+="</tr>"}return e+="</table>",e+='<div class="mce-text-center">0 x 0</div>'}var b,C,x=this;r.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",onhide:function(){r.dom.removeClass(this.menu.items()[0].getEl().getElementsByTagName("a"),"mce-active")},menu:[{type:"container",html:y(),onmousemove:function(e){var t=e.target;if("A"==t.nodeName){var n=r.dom.getParent(t,"table"),i=t.getAttribute("data-mce-index");if(i!=this.lastPos){i=i.split(","),i[0]=parseInt(i[0],10),i[1]=parseInt(i[1],10);for(var o=0;10>o;o++)for(var a=0;10>a;a++)r.dom.toggleClass(n.rows[o].childNodes[a].firstChild,"mce-active",a<=i[0]&&o<=i[1]);n.nextSibling.innerHTML=i[0]+1+" x "+(i[1]+1),this.lastPos=i}}},onclick:function(e){"A"==e.target.nodeName&&this.lastPos&&(e.preventDefault(),m(this.lastPos[0]+1,this.lastPos[1]+1),this.parent().cancel())}}]}),r.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:g,onclick:c}),r.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:g,cmd:"mceTableDelete"}),r.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:p("mceTableCellProps"),onPostRender:v},{text:"Merge cells",onclick:p("mceTableMergeCells"),onPostRender:v},{text:"Split cell",onclick:p("mceTableSplitCells"),onPostRender:v}]}),r.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:p("mceTableInsertRowBefore"),onPostRender:v},{text:"Insert row after",onclick:p("mceTableInsertRowAfter"),onPostRender:v},{text:"Delete row",onclick:p("mceTableDeleteRow"),onPostRender:v},{text:"Row properties",onclick:p("mceTableRowProps"),onPostRender:v},{text:"-"},{text:"Cut row",onclick:p("mceTableCutRow"),onPostRender:v},{text:"Copy row",onclick:p("mceTableCopyRow"),onPostRender:v},{text:"Paste row before",onclick:p("mceTablePasteRowBefore"),onPostRender:v},{text:"Paste row after",onclick:p("mceTablePasteRowAfter"),onPostRender:v}]}),r.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:p("mceTableInsertColBefore"),onPostRender:v},{text:"Insert column after",onclick:p("mceTableInsertColAfter"),onPostRender:v},{text:"Delete column",onclick:p("mceTableDeleteCol"),onPostRender:v}]});var w=[];l("inserttable tableprops deletetable | cell row column".split(" "),function(e){"|"==e?w.push({text:"-"}):w.push(r.menuItems[e])}),r.addButton("table",{type:"menubutton",title:"Table",menu:w}),o.isIE||r.on("click",function(e){e=e.target,"TABLE"===e.nodeName&&(r.selection.select(e),r.nodeChanged())}),x.quirks=new t(r),r.on("Init",function(){b=r.windowManager,x.cellSelection=new n(r)}),l({mceTableSplitCells:function(e){e.split()},mceTableMergeCells:function(e){var t,n,i;i=r.dom.getParent(r.selection.getStart(),"th,td"),i&&(t=i.rowSpan,n=i.colSpan),r.dom.select("td.mce-item-selected,th.mce-item-selected").length?e.merge():d(e,i)},mceTableInsertRowBefore:function(e){e.insertRow(!0)},mceTableInsertRowAfter:function(e){e.insertRow()},mceTableInsertColBefore:function(e){e.insertCol(!0)},mceTableInsertColAfter:function(e){e.insertCol()},mceTableDeleteCol:function(e){e.deleteCols()},mceTableDeleteRow:function(e){e.deleteRows()},mceTableCutRow:function(e){C=e.cutRows()},mceTableCopyRow:function(e){C=e.copyRows()},mceTablePasteRowBefore:function(e){e.pasteRows(C,!0)},mceTablePasteRowAfter:function(e){e.pasteRows(C)},mceTableDelete:function(e){e.deleteTable()}},function(t,n){r.addCommand(n,function(){var n=new e(r);n&&(t(n),r.execCommand("mceRepaint"),x.cellSelection.clear())})}),l({mceInsertTable:function(){c()},mceTableRowProps:f,mceTableCellProps:u},function(e,t){r.addCommand(t,function(t,n){e(n)})})}var l=r.each;a.add("table",s)}),a([l,u,p,h])}(this);
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/template/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/template/plugin.min.js new file mode 100644 index 00000000..d628daa1 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/template/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("template",function(e){function t(){function t(e){var t=e.control.value();t.url?tinymce.util.XHR.send({url:t.url,success:function(e){a=e,n.find("iframe")[0].html(e)}}):(a=t.content,n.find("iframe")[0].html(t.content)),n.find("#description")[0].text(e.control.value().description)}var n,a,r=[];return e.settings.templates?(tinymce.each(e.settings.templates,function(e){r.push({selected:!r.length,text:e.title,value:{url:e.url,content:e.content,description:e.description}})}),n=e.windowManager.open({title:"Insert template",body:[{type:"listbox",name:"template",flex:0,label:"Templates",values:r,onselect:t},{type:"label",name:"description",label:"Description",text:"Â "},{type:"iframe",minWidth:600,minHeight:400,border:1}],onsubmit:function(){i(!1,a)}}),n.find("listbox")[0].fire("select"),void 0):(e.windowManager.alert("No templates defined"),void 0)}function n(t,n){function a(e,t){if(e=""+e,e.length<t)for(var n=0;n<t-e.length;n++)e="0"+e;return e}var i="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),r="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),o="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),l="January February March April May June July August September October November December".split(" ");return n=n||new Date,t=t.replace("%D","%m/%d/%Y"),t=t.replace("%r","%I:%M:%S %p"),t=t.replace("%Y",""+n.getFullYear()),t=t.replace("%y",""+n.getYear()),t=t.replace("%m",a(n.getMonth()+1,2)),t=t.replace("%d",a(n.getDate(),2)),t=t.replace("%H",""+a(n.getHours(),2)),t=t.replace("%M",""+a(n.getMinutes(),2)),t=t.replace("%S",""+a(n.getSeconds(),2)),t=t.replace("%I",""+((n.getHours()+11)%12+1)),t=t.replace("%p",""+(n.getHours()<12?"AM":"PM")),t=t.replace("%B",""+e.translate(l[n.getMonth()])),t=t.replace("%b",""+e.translate(o[n.getMonth()])),t=t.replace("%A",""+e.translate(r[n.getDay()])),t=t.replace("%a",""+e.translate(i[n.getDay()])),t=t.replace("%%","%")}function a(t){var n=e.dom,a=e.getParam("template_replace_values");r(n.select("*",t),function(e){r(a,function(t,i){n.hasClass(e,i)&&"function"==typeof a[i]&&a[i](e)})})}function i(t,i){function o(e,t){return new RegExp("\\b"+t+"\\b","g").test(e.className)}var l,c,s=e.dom,d=e.selection.getContent();r(e.getParam("template_replace_values"),function(e,t){"function"!=typeof e&&(i=i.replace(new RegExp("\\{\\$"+t+"\\}","g"),e))}),l=s.create("div",null,i),c=s.select(".mceTmpl",l),c&&c.length>0&&(l=s.create("div",null),l.appendChild(c[0].cloneNode(!0))),r(s.select("*",l),function(t){o(t,e.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_cdate_format",e.getLang("template.cdate_format")))),o(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format")))),o(t,e.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))&&(t.innerHTML=d)}),a(l),e.execCommand("mceInsertContent",!1,l.innerHTML),e.addVisual()}var r=tinymce.each;e.addCommand("mceInsertTemplate",i),e.addButton("template",{title:"Insert template",onclick:t}),e.addMenuItem("template",{text:"Insert template",onclick:t,context:"insert"}),e.on("PreProcess",function(t){var i=e.dom;r(i.select("div",t.node),function(t){i.hasClass(t,"mceTmpl")&&(r(i.select("*",t),function(t){i.hasClass(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format"))))}),a(t))})})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/textcolor/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/textcolor/plugin.min.js new file mode 100644 index 00000000..201f4e54 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/textcolor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("textcolor",function(e){function t(){var t,n,a=[];for(n=e.settings.textcolor_map||["000000","Black","993300","Burnt orange","333300","Dark olive","003300","Dark green","003366","Dark azure","000080","Navy Blue","333399","Indigo","333333","Very dark gray","800000","Maroon","FF6600","Orange","808000","Olive","008000","Green","008080","Teal","0000FF","Blue","666699","Grayish blue","808080","Gray","FF0000","Red","FF9900","Amber","99CC00","Yellow green","339966","Sea green","33CCCC","Turquoise","3366FF","Royal blue","800080","Purple","999999","Medium gray","FF00FF","Magenta","FFCC00","Gold","FFFF00","Yellow","00FF00","Lime","00FFFF","Aqua","00CCFF","Sky blue","993366","Brown","C0C0C0","Silver","FF99CC","Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum","FFFFFF","White"],t=0;t<n.length;t+=2)a.push({text:n[t+1],color:n[t]});return a}function n(){var n,a,i,r,o,l,c,s,d,u=this;for(n=t(),i='<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="presentation" cellspacing="0"><tbody>',r=n.length-1,o=e.settings.textcolor_rows||5,l=e.settings.textcolor_cols||8,s=0;o>s;s++){for(i+="<tr>",c=0;l>c;c++)d=s*l+c,d>r?i+="<td></td>":(a=n[d],i+='<td><div id="'+u._id+"-"+d+'"'+' data-mce-color="'+a.color+'"'+' role="option"'+' tabIndex="-1"'+' style="'+(a?"background-color: #"+a.color:"")+'"'+' title="'+a.text+'">'+"</div>"+"</td>");i+="</tr>"}return i+="</tbody></table>"}function a(t){var n,a=this.parent();(n=t.target.getAttribute("data-mce-color"))&&(a.hidePanel(),n="#"+n,a.color(n),e.execCommand(a.settings.selectcmd,!1,n))}function i(){var t=this;t._color&&e.execCommand(t.settings.selectcmd,!1,t._color)}e.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",popoverAlign:"bc-tl",selectcmd:"ForeColor",panel:{html:n,onclick:a},onclick:i}),e.addButton("backcolor",{type:"colorbutton",tooltip:"Background color",popoverAlign:"bc-tl",selectcmd:"HiliteColor",panel:{html:n,onclick:a},onclick:i})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/visualblocks/css/visualblocks.css b/extlib/tinymce/js/tinymce/plugins/visualblocks/css/visualblocks.css new file mode 100644 index 00000000..7a3a47a3 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/visualblocks/css/visualblocks.css @@ -0,0 +1,114 @@ +.mce-visualblocks p { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7); +} + +.mce-visualblocks h1 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==); +} + +.mce-visualblocks h2 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==); +} + +.mce-visualblocks h3 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7); +} + +.mce-visualblocks h4 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==); +} + +.mce-visualblocks h5 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==); +} + +.mce-visualblocks h6 { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==); +} + +.mce-visualblocks div { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7); +} + +.mce-visualblocks section { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=); +} + +.mce-visualblocks article { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7); +} + +.mce-visualblocks blockquote { + padding-top: 10px; + border: 1px dashed #BBB; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7); +} + +.mce-visualblocks address { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=); +} + +.mce-visualblocks pre { + padding-top: 10px; + border: 1px dashed #BBB; + margin-left: 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==); +} + +.mce-visualblocks figure { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7); +} + +.mce-visualblocks hgroup { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7); +} + +.mce-visualblocks aside { + padding-top: 10px; + border: 1px dashed #BBB; + margin: 0 0 1em 3px; + background: transparent no-repeat url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=); +} + +.mce-visualblocks figcaption { + border: 1px dashed #BBB; +} diff --git a/extlib/tinymce/js/tinymce/plugins/visualblocks/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/visualblocks/plugin.min.js new file mode 100644 index 00000000..1cb40081 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/visualblocks/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualblocks",function(e,t){function n(){var t=this;e.on("VisualBlocks",function(){t.active(e.dom.hasClass(e.getBody(),"mce-visualblocks"))})}var i,a,r;window.NodeList&&(e.addCommand("mceVisualBlocks",function(){var n,o=e.dom;i||(i=o.uniqueId(),n=o.create("link",{id:i,rel:"stylesheet",href:t+"/css/visualblocks.css"}),e.getDoc().getElementsByTagName("head")[0].appendChild(n)),e.on("PreviewFormats AfterPreviewFormats",function(t){r&&o.toggleClass(e.getBody(),"mce-visualblocks","afterpreviewformats"==t.type)}),o.toggleClass(e.getBody(),"mce-visualblocks"),r=e.dom.hasClass(e.getBody(),"mce-visualblocks"),a&&a.active(o.hasClass(e.getBody(),"mce-visualblocks")),e.fire("VisualBlocks")}),e.addButton("visualblocks",{title:"Show blocks",cmd:"mceVisualBlocks",onPostRender:n}),e.addMenuItem("visualblocks",{text:"Show blocks",cmd:"mceVisualBlocks",onPostRender:n,selectable:!0,context:"view",prependToContext:!0}),e.on("init",function(){e.settings.visualblocks_default_state&&e.execCommand("mceVisualBlocks",!1,null,{skip_focus:!0})}),e.on("remove",function(){e.dom.removeClass(e.getBody(),"mce-visualblocks")}))});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/visualchars/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/visualchars/plugin.min.js new file mode 100644 index 00000000..44742388 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/visualchars/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualchars",function(e){function t(t){var n,a,r,o,l,s,c=e.getBody(),d=e.selection;if(i=!i,e.fire("VisualChars",{state:i}),t&&(s=d.getBookmark()),i)for(a=[],tinymce.walk(c,function(e){3==e.nodeType&&e.nodeValue&&-1!=e.nodeValue.indexOf("Â ")&&a.push(e)},"childNodes"),r=0;r<a.length;r++){for(o=a[r].nodeValue,o=o.replace(/(\u00a0)/g,'<span data-mce-bogus="1" class="mce-nbsp">$1</span>'),l=e.dom.create("div",null,o);n=l.lastChild;)e.dom.insertAfter(n,a[r]);e.dom.remove(a[r])}else for(a=e.dom.select("span.mce-nbsp",c),r=a.length-1;r>=0;r--)e.dom.remove(a[r],1);d.moveToBookmark(s)}function n(){var t=this;e.on("VisualChars",function(e){t.active(e.state)})}var i;e.addCommand("mceVisualChars",t),e.addButton("visualchars",{title:"Show invisible characters",cmd:"mceVisualChars",onPostRender:n}),e.addMenuItem("visualchars",{text:"Show invisible characters",cmd:"mceVisualChars",onPostRender:n,selectable:!0,context:"view",prependToContext:!0}),e.on("beforegetcontent",function(e){i&&"raw"!=e.format&&!e.draft&&(i=!0,t(!1))})});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/plugins/wordcount/plugin.min.js b/extlib/tinymce/js/tinymce/plugins/wordcount/plugin.min.js new file mode 100644 index 00000000..8c419801 --- /dev/null +++ b/extlib/tinymce/js/tinymce/plugins/wordcount/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("wordcount",function(e){function t(){e.theme.panel.find("#wordcount").text(["Words: {0}",a.getCount()])}var n,i,a=this;n=e.getParam("wordcount_countregex",/[\w\u2019\x27\-]+/g),i=e.getParam("wordcount_cleanregex",/[0-9.(),;:!?%#$?\x27\x22_+=\\\/\-]*/g),e.on("init",function(){var n=e.theme.panel&&e.theme.panel.find("#statusbar")[0];n&&window.setTimeout(function(){n.insert({type:"label",name:"wordcount",text:["Words: {0}",a.getCount()],classes:"wordcount"},0),e.on("setcontent beforeaddundo",t),e.on("keyup",function(e){32==e.keyCode&&t()})},0)}),a.getCount=function(){var t=e.getContent({format:"raw"}),a=0;if(t){t=t.replace(/\.\.\./g," "),t=t.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," "),t=t.replace(/(\w+)(&.+?;)+(\w+)/,"$1$3").replace(/&.+?;/g," "),t=t.replace(i,"");var o=t.match(n);o&&(a=o.length)}return a}});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/content.inline.min.css b/extlib/tinymce/js/tinymce/skins/lightgray/content.inline.min.css new file mode 100644 index 00000000..771b83e5 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/content.inline.min.css @@ -0,0 +1 @@ +.mce-object{border:1px dotted #3a3a3a;background:#d5d5d5 url(img/object.gif) no-repeat center}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px!important;height:9px!important;border:1px dotted #3a3a3a;background:#d5d5d5 url(img/anchor.gif) no-repeat center}.mce-nbsp{background:#AAA}hr{cursor:default}.mce-match-marker{background:green;color:#fff}.mce-spellchecker-word{background:url(img/wline.gif) repeat-x bottom left;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td.mce-item-selected,th.mce-item-selected{background-color:#39f!important}.mce-edit-focus{outline:1px dotted #333}
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/content.min.css b/extlib/tinymce/js/tinymce/skins/lightgray/content.min.css new file mode 100644 index 00000000..b9bbab14 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/content.min.css @@ -0,0 +1 @@ +body{background-color:#fff;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;scrollbar-3dlight-color:#f0f0ee;scrollbar-arrow-color:#676662;scrollbar-base-color:#f0f0ee;scrollbar-darkshadow-color:#ddd;scrollbar-face-color:#e0e0dd;scrollbar-highlight-color:#f0f0ee;scrollbar-shadow-color:#f0f0ee;scrollbar-track-color:#f5f5f5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px}.mce-object{border:1px dotted #3a3a3a;background:#d5d5d5 url(img/object.gif) no-repeat center}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px!important;height:9px!important;border:1px dotted #3a3a3a;background:#d5d5d5 url(img/anchor.gif) no-repeat center}.mce-nbsp{background:#AAA}hr{cursor:default}.mce-match-marker{background:green;color:#fff}.mce-spellchecker-word{background:url(img/wline.gif) repeat-x bottom left;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td.mce-item-selected,th.mce-item-selected{background-color:#39f!important}.mce-edit-focus{outline:1px dotted #333}
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.eot b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.eot Binary files differnew file mode 100644 index 00000000..42a34a57 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.eot diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.svg b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.svg new file mode 100644 index 00000000..93a8f347 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.svg @@ -0,0 +1,166 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata> +This is a custom SVG font generated by IcoMoon. +<iconset grid="16"></iconset> +</metadata> +<defs> +<font id="icomoon-small" horiz-adv-x="512" > +<font-face units-per-em="512" ascent="480" descent="-32" /> +<missing-glyph horiz-adv-x="512" /> +<glyph unicode="" d="M 352.00,64.00l0.00,18.502 c 75.674,30.814, 128.00,96.91, 128.00,173.498c0.00,106.039-100.288,192.00-224.00,192.00S 32.00,362.039, 32.00,256.00 + c0.00-76.588, 52.327-142.684, 128.00-173.498L 160.00,64.00 L 64.00,64.00 l-32.00,48.00l0.00-112.00 l 160.00,0.00 L 192.00,111.406 c-50.45,25.681-85.333,80.77-85.333,144.594 + c0.00,88.366, 66.859,160.00, 149.333,160.00c 82.474,0.00, 149.333-71.634, 149.333-160.00c0.00-63.824-34.883-118.913-85.333-144.594L 320.00,0.00 l 160.00,0.00 L 480.00,112.00 l-32.00-48.00 + L 352.00,64.00 z" /> +<glyph unicode="" d="M 128.00,448.00l0.00-448.00 l 128.00,128.00l 128.00-128.00L 384.00,448.00 L 128.00,448.00 z M 352.00,85.255l-96.00,96.00l-96.00-96.00L 160.00,416.00 l 192.00,0.00 L 352.00,85.255 z" /> +<glyph unicode="" d="M 463.637,364.892l-66.745,66.744C 386.34,442.188, 372.276,448.00, 357.293,448.00s-29.047-5.812-39.598-16.363l-82.746-82.745 + c-21.834-21.834-21.834-57.362,0.00-79.196l 1.373-1.373l 33.941,33.941l-1.373,1.373c-3.066,3.066-3.066,8.247,0.00,11.313l 82.746,82.746 + C 353.641,399.70, 356.04,400.00, 357.292,400.00s 3.651-0.299, 5.656-2.305l 66.745-66.744c 3.066-3.067, 3.066-8.249, 0.001-11.314l-82.747-82.747 + c-2.004-2.004-4.403-2.304-5.655-2.304s-3.651,0.30-5.656,2.306l-1.373,1.373l-33.94-33.942l 1.371-1.371 + c 10.553-10.554, 24.615-16.364, 39.60-16.364s 29.047,5.812, 39.598,16.363l 82.747,82.746C 485.47,307.53, 485.47,343.057, 463.637,364.892 + zM 275.678,179.678l-33.941-33.941l 1.373-1.373c 2.004-2.004, 2.305-4.403, 2.305-5.655c0.00-1.253-0.299-3.651-2.303-5.657 + l-82.747-82.745c-2.005-2.005-4.405-2.305-5.657-2.305s-3.652,0.30-5.657,2.305L 82.305,117.05C 80.30,119.055, 80.00,121.455, 80.00,122.707 + s 0.299,3.65, 2.305,5.656l 82.745,82.744c 2.005,2.006, 4.405,2.306, 5.657,2.306s 3.652-0.30, 5.657-2.306l 1.373-1.371l 33.941,33.94 + l-1.373,1.373c-10.552,10.552-24.615,16.363-39.598,16.363s-29.046-5.812-39.598-16.363l-82.744-82.743 + C 37.812,151.754, 32.00,137.689, 32.00,122.707s 5.812-29.047, 16.363-39.599l 66.745-66.745C 125.661,5.812, 139.724,0.00, 154.707,0.00 + s 29.046,5.812, 39.598,16.363l 82.747,82.746c 10.552,10.552, 16.361,24.615, 16.361,39.598s-5.812,29.047-16.363,39.598 + L 275.678,179.678zM 400.00,61.00c-4.862,0.00-9.725,1.854-13.435,5.565l-64.00,63.999c-7.422,7.42-7.422,19.449,0.00,26.869 + c 7.42,7.422, 19.448,7.422, 26.868,0.00l 64.00-64.00c 7.422-7.42, 7.422-19.448,0.00-26.868C 409.725,62.854, 404.862,61.00, 400.00,61.00zM 304.00,0.00c-8.837,0.00-16.00,7.163-16.00,16.00l0.00,64.00 c0.00,8.837, 7.163,16.00, 16.00,16.00s 16.00-7.163, 16.00-16.00l0.00-64.00 C 320.00,7.163, 312.837,0.00, 304.00,0.00zM 464.00,160.00l-64.00,0.00 c-8.837,0.00-16.00,7.163-16.00,16.00s 7.163,16.00, 16.00,16.00l 64.00,0.00 c 8.837,0.00, 16.00-7.163, 16.00-16.00S 472.837,160.00, 464.00,160.00zM 112.00,387.00c 4.862,0.00, 9.725-1.854, 13.435-5.565l 64.00-64.00c 7.421-7.42, 7.421-19.449,0.00-26.869c-7.42-7.422-19.449-7.422-26.869,0.00 + l-64.00,64.00c-7.421,7.42-7.421,19.449,0.00,26.869C 102.275,385.146, 107.138,387.00, 112.00,387.00zM 208.00,448.00c 8.837,0.00, 16.00-7.163, 16.00-16.00l0.00-64.00 c0.00-8.837-7.163-16.00-16.00-16.00s-16.00,7.163-16.00,16.00L 192.00,432.00 C 192.00,440.837, 199.163,448.00, 208.00,448.00zM 48.00,288.00l 64.00,0.00 c 8.837,0.00, 16.00-7.163, 16.00-16.00s-7.163-16.00-16.00-16.00L 48.00,256.00 c-8.837,0.00-16.00,7.163-16.00,16.00S 39.163,288.00, 48.00,288.00z" /> +<glyph unicode="" d="M 463.637,364.892l-66.745,66.744C 386.34,442.188, 372.276,448.00, 357.293,448.00s-29.047-5.812-39.598-16.363l-82.746-82.745 + c-21.834-21.834-21.834-57.362,0.00-79.196l 1.373-1.373l 33.941,33.941l-1.373,1.373c-3.066,3.066-3.066,8.247,0.00,11.313l 82.746,82.746 + C 353.641,399.70, 356.04,400.00, 357.292,400.00s 3.651-0.299, 5.656-2.305l 66.745-66.744c 3.066-3.067, 3.066-8.249, 0.001-11.314l-82.747-82.747 + c-2.004-2.004-4.403-2.304-5.655-2.304s-3.651,0.30-5.656,2.306l-1.373,1.373l-33.94-33.942l 1.371-1.371 + c 10.553-10.554, 24.615-16.364, 39.60-16.364s 29.047,5.812, 39.598,16.363l 82.747,82.746C 485.47,307.53, 485.47,343.057, 463.637,364.892 + zM 275.678,179.678l-33.941-33.941l 1.373-1.373c 2.004-2.004, 2.305-4.403, 2.305-5.655c0.00-1.253-0.299-3.651-2.303-5.657 + l-82.747-82.745c-2.005-2.005-4.405-2.305-5.657-2.305s-3.652,0.30-5.657,2.305L 82.305,117.05C 80.30,119.055, 80.00,121.455, 80.00,122.707 + s 0.299,3.65, 2.305,5.656l 82.745,82.744c 2.005,2.006, 4.405,2.306, 5.657,2.306s 3.652-0.30, 5.657-2.306l 1.373-1.371l 33.941,33.94 + l-1.373,1.373c-10.552,10.552-24.615,16.363-39.598,16.363s-29.046-5.812-39.598-16.363l-82.744-82.743 + C 37.812,151.754, 32.00,137.689, 32.00,122.707s 5.812-29.047, 16.363-39.599l 66.745-66.745C 125.661,5.812, 139.724,0.00, 154.707,0.00 + s 29.046,5.812, 39.598,16.363l 82.747,82.746c 10.552,10.552, 16.361,24.615, 16.361,39.598s-5.812,29.047-16.363,39.598 + L 275.678,179.678zM 176.00,125.00c-4.862,0.00-9.725,1.855-13.435,5.564c-7.42,7.42-7.42,19.449,0.00,26.869l 160.00,160.00c 7.42,7.42, 19.448,7.42, 26.868,0.00 + c 7.422-7.42, 7.422-19.45,0.00-26.87l-160.00-160.00C 185.725,126.855, 180.862,125.00, 176.00,125.00z" /> +<glyph unicode="" d="M 288.00,339.337L 288.00,448.00 l 168.001-168.00L 288.00,112.00L 288.00,223.048 C 92.547,227.633, 130.50,99.50, 160.00,0.00C 16.00,160.00, 53.954,345.437, 288.00,339.337z" /> +<glyph unicode="" d="M 352.00,0.00c 29.50,99.50, 67.453,227.633-128.00,223.048L 224.00,112.00 L 55.999,280.00L 224.00,448.00l0.00-108.663 C 458.046,345.437, 496.00,160.00, 352.00,0.00z" /> +<glyph unicode="" d="M 128.214,267.637c 52.90,0.00, 95.786-45.585, 95.786-101.819C 224.00,109.586, 181.114,64.00, 128.214,64.00 + c-52.901,0.00-95.786,45.585-95.786,101.818L 32.00,180.364C 32.00,292.829, 117.77,384.00, 223.572,384.00l0.00-58.182 c-36.55,0.00-70.913-15.13-96.758-42.602 + c-4.977-5.289-9.517-10.917-13.612-16.828C 118.094,267.208, 123.105,267.637, 128.214,267.637zM 384.214,267.637c 52.90,0.00, 95.786-45.585, 95.786-101.819C 480.00,109.586, 437.114,64.00, 384.214,64.00 + c-52.901,0.00-95.786,45.585-95.786,101.818L 288.00,180.364C 288.00,292.829, 373.77,384.00, 479.572,384.00l0.00-58.182 c-36.55,0.00-70.913-15.13-96.758-42.602 + c-4.978-5.289-9.518-10.917-13.612-16.828C 374.094,267.208, 379.105,267.637, 384.214,267.637z" /> +<glyph unicode="" d="M 32.00,384.00L 480.00,384.00L 480.00,320.00L 32.00,320.00zM 192.00,192.00L 480.00,192.00L 480.00,128.00L 192.00,128.00zM 192.00,288.00L 480.00,288.00L 480.00,224.00L 192.00,224.00zM 32.00,96.00L 480.00,96.00L 480.00,32.00L 32.00,32.00zM 32.00,288.00L 144.00,208.00L 32.00,128.00 z" /> +<glyph unicode="" d="M 32.00,384.00L 480.00,384.00L 480.00,320.00L 32.00,320.00zM 32.00,192.00L 320.00,192.00L 320.00,128.00L 32.00,128.00zM 32.00,288.00L 320.00,288.00L 320.00,224.00L 32.00,224.00zM 32.00,96.00L 480.00,96.00L 480.00,32.00L 32.00,32.00zM 480.00,288.00L 368.00,208.00L 480.00,128.00 z" /> +<glyph unicode="" d="M 192.00,416.00L 480.00,416.00L 480.00,352.00L 192.00,352.00zM 192.00,256.00L 480.00,256.00L 480.00,192.00L 192.00,192.00zM 192.00,96.00L 480.00,96.00L 480.00,32.00L 192.00,32.00zM 160.00,215.00L 160.00,288.00L 128.00,288.00L 128.00,448.00L 64.00,448.00L 64.00,416.00L 96.00,416.00L 96.00,288.00L 64.00,288.00L 64.00,256.00L 128.00,256.00L 128.00,231.00L 64.00,201.00L 64.00,128.00L 128.00,128.00L 128.00,96.00L 64.00,96.00L 64.00,64.00L 128.00,64.00L 128.00,32.00L 64.00,32.00L 64.00,0.00L 160.00,0.00L 160.00,160.00L 96.00,160.00L 96.00,185.00 z" /> +<glyph unicode="" d="M 192.00,416.00L 480.00,416.00L 480.00,352.00L 192.00,352.00zM 192.00,256.00L 480.00,256.00L 480.00,192.00L 192.00,192.00zM 192.00,96.00L 480.00,96.00L 480.00,32.00L 192.00,32.00zM 64.00,384.00A32.00,32.00 1620.00 1 1 128.00,384A32.00,32.00 1620.00 1 1 64.00,384zM 64.00,224.00A32.00,32.00 1620.00 1 1 128.00,224A32.00,32.00 1620.00 1 1 64.00,224zM 64.00,64.00A32.00,32.00 1620.00 1 1 128.00,64A32.00,32.00 1620.00 1 1 64.00,64z" /> +<glyph unicode="" d="M 444.00,288.00l-28.00,0.00 L 416.00,416.00 l 32.00,0.00 L 448.00,448.00 L 288.00,448.00 l0.00-32.00 l 32.00,0.00 l0.00-128.00 L 192.00,288.00 L 192.00,416.00 l 32.00,0.00 L 224.00,448.00 L 64.00,448.00 l0.00-32.00 l 32.00,0.00 l0.00-128.00 L 68.00,288.00 c-19.80,0.00-36.00-16.20-36.00-36.00l0.00-216.00 c0.00-19.80, 16.20-36.00, 36.00-36.00l 120.00,0.00 + c 19.80,0.00, 36.00,16.20, 36.00,36.00L 224.00,192.00 l 64.00,0.00 l0.00-156.00 c0.00-19.80, 16.20-36.00, 36.00-36.00l 120.00,0.00 c 19.80,0.00, 36.00,16.20, 36.00,36.00L 480.00,252.00 C 480.00,271.80, 463.80,288.00, 444.00,288.00z M 174.00,32.00L 82.00,32.00 + c-9.90,0.00-18.00,7.20-18.00,16.00s 8.10,16.00, 18.00,16.00l 92.00,0.00 c 9.90,0.00, 18.00-7.20, 18.00-16.00S 183.90,32.00, 174.00,32.00z M 272.00,224.00l-32.00,0.00 c-8.80,0.00-16.00,7.20-16.00,16.00s 7.20,16.00, 16.00,16.00l 32.00,0.00 + c 8.80,0.00, 16.00-7.20, 16.00-16.00S 280.80,224.00, 272.00,224.00z M 430.00,32.00l-92.00,0.00 c-9.90,0.00-18.00,7.20-18.00,16.00s 8.10,16.00, 18.00,16.00l 92.00,0.00 c 9.90,0.00, 18.00-7.20, 18.00-16.00S 439.90,32.00, 430.00,32.00z" /> +<glyph unicode="" d="M 352.00,288.00l0.00,80.00 c0.00,8.80-7.20,16.00-16.00,16.00l-80.00,0.00 L 256.00,416.00 c0.00,17.60-14.40,32.00-32.00,32.00l-64.00,0.00 c-17.602,0.00-32.00-14.40-32.00-32.00l0.00-32.00 L 48.00,384.00 c-8.801,0.00-16.00-7.20-16.00-16.00l0.00-256.00 + c0.00-8.80, 7.199-16.00, 16.00-16.00l 112.00,0.00 l0.00-96.00 l 192.00,0.00 l 96.00,96.00L 448.00,288.00 L 352.00,288.00 z M 160.00,415.943c 0.017,0.019, 0.036,0.039, 0.057,0.057l 63.884,0.00 + c 0.021-0.018, 0.041-0.038, 0.059-0.057L 224.00,384.00 l-64.00,0.00 L 160.00,415.943 L 160.00,415.943z M 96.00,320.00l0.00,32.00 l 192.00,0.00 l0.00-32.00 L 96.00,320.00 z M 352.00,45.255L 352.00,96.00 l 50.745,0.00 L 352.00,45.255z + M 416.00,128.00l-96.00,0.00 l0.00-96.00 L 192.00,32.00 L 192.00,256.00 l 224.00,0.00 L 416.00,128.00 z" /> +<glyph unicode="" d="M 416.00,320.00l-96.00,0.00 l0.00,32.00 l-96.00,96.00L 32.00,448.00 l0.00-352.00 l 192.00,0.00 l0.00-96.00 l 288.00,0.00 L 512.00,224.00 L 416.00,320.00z M 416.00,274.745L 466.745,224.00L 416.00,224.00 L 416.00,274.745 z M 224.00,402.745L 274.745,352.00 + L 224.00,352.00 L 224.00,402.745 z M 64.00,416.00l 128.00,0.00 l0.00-96.00 l 96.00,0.00 l0.00-192.00 L 64.00,128.00 L 64.00,416.00 z M 480.00,32.00L 256.00,32.00 l0.00,64.00 l 64.00,0.00 L 320.00,288.00 l 64.00,0.00 l0.00-96.00 l 96.00,0.00 L 480.00,32.00 z" /> +<glyph unicode="" d="M 432.204,144.934c-23.235,23.235-53.469,34.002-80.541,31.403L 320.00,208.00l 96.00,96.00c0.00,0.00, 64.00,64.00,0.00,128.00L 256.00,272.00L 96.00,432.00 + c-64.00-64.00,0.00-128.00,0.00-128.00l 96.00-96.00l-31.663-31.663c-27.072,2.599-57.305-8.169-80.54-31.403c-37.49-37.49-42.556-93.209-11.313-124.45 + c 31.241-31.241, 86.96-26.177, 124.45,11.313c 23.235,23.234, 34.001,53.469, 31.403,80.54L 256.00,144.00l 31.664-31.664 + c-2.598-27.072, 8.168-57.305, 31.403-80.539c 37.489-37.49, 93.209-42.556, 124.449-11.313 + C 474.76,51.725, 469.694,107.443, 432.204,144.934z M 176.562,100.711c-1.106-12.166-7.51-24.913-17.57-34.973 + C 147.886,54.631, 133.452,48.00, 120.383,48.00c-5.262,0.00-12.649,1.114-17.958,6.424c-10.703,10.702-8.688,36.566, 11.313,56.568 + c 11.106,11.107, 25.54,17.738, 38.609,17.738c 5.262,0.00, 12.649-1.114, 17.958-6.424C 176.861,115.751, 177.04,105.962, 176.562,100.711z + M 256.00,176.00c-17.673,0.00-32.00,14.327-32.00,32.00s 14.327,32.00, 32.00,32.00s 32.00-14.327, 32.00-32.00S 273.673,176.00, 256.00,176.00z M 409.576,54.424 + c-5.31-5.31-12.696-6.424-17.958-6.424c-13.069,0.00-27.503,6.631-38.609,17.738c-10.061,10.06-16.464,22.807-17.569,34.973 + c-0.479,5.251-0.30,15.04, 6.257,21.596c 5.309,5.311, 12.695,6.424, 17.958,6.424c 13.068,0.00, 27.503-6.631, 38.608-17.737 + C 418.265,90.99, 420.279,65.126, 409.576,54.424z" /> +<glyph unicode="" d="M 32.00,384.00L 480.00,384.00L 480.00,320.00L 32.00,320.00zM 32.00,192.00L 480.00,192.00L 480.00,128.00L 32.00,128.00zM 32.00,288.00L 480.00,288.00L 480.00,224.00L 32.00,224.00zM 32.00,96.00L 480.00,96.00L 480.00,32.00L 32.00,32.00z" /> +<glyph unicode="" d="M 32.00,384.00L 480.00,384.00L 480.00,320.00L 32.00,320.00zM 32.00,192.00L 480.00,192.00L 480.00,128.00L 32.00,128.00zM 128.00,288.00L 384.00,288.00L 384.00,224.00L 128.00,224.00zM 128.00,96.00L 384.00,96.00L 384.00,32.00L 128.00,32.00z" /> +<glyph unicode="" d="M 32.00,384.00L 480.00,384.00L 480.00,320.00L 32.00,320.00zM 32.00,192.00L 480.00,192.00L 480.00,128.00L 32.00,128.00zM 192.00,288.00L 480.00,288.00L 480.00,224.00L 192.00,224.00zM 192.00,96.00L 480.00,96.00L 480.00,32.00L 192.00,32.00z" /> +<glyph unicode="" d="M 32.00,384.00L 480.00,384.00L 480.00,320.00L 32.00,320.00zM 32.00,192.00L 480.00,192.00L 480.00,128.00L 32.00,128.00zM 32.00,288.00L 320.00,288.00L 320.00,224.00L 32.00,224.00zM 32.00,96.00L 320.00,96.00L 320.00,32.00L 32.00,32.00z" /> +<glyph unicode="" d="M 480.00,224.00l-4.571,0.00 L 347.062,224.00 c-25.039,17.71-57.215,27.43-91.062,27.43c-44.603,0.00-82.286,25.121-82.286,54.856 + c0.00,29.735, 37.683,54.857, 82.286,54.857c 37.529,0.00, 70.154-17.788, 79.56-41.143l 56.508,0.00 c-3.965,25.322-18.79,48.984-42.029,66.413 + C 324.599,405.493, 291.201,416.00, 256.00,416.00c-35.202,0.00-68.598-10.507-94.037-29.587c-27.394-20.545-43.106-49.751-43.106-80.127 + s 15.712-59.582, 43.106-80.127c 0.978-0.733, 1.971-1.449, 2.973-2.158L 36.571,224.001 L 32.00,224.001 l0.00-32.00 l 256.266,0.00 c 29.104-8.553, 50.021-28.135, 50.021-50.286 + c0.00-29.734-37.684-54.855-82.286-54.855c-37.53,0.00-70.154,17.787-79.559,41.143l-56.508,0.00 c 3.965-25.32, 18.791-48.984, 42.03-66.413 + C 187.402,42.508, 220.798,32.00, 256.00,32.00c 35.201,0.00, 68.599,10.508, 94.037,29.587c 27.395,20.545, 43.104,49.751, 43.104,80.127 + c0.00,17.649-5.327,34.896-15.147,50.286L 480.00,192.00 L 480.00,224.00 z" /> +<glyph unicode="" d="M 96.00,64.00l 288.00,0.00 l0.00-32.00 L 96.00,32.00 L 96.00,64.00 zM 320.00,416.00l0.00-192.00 c0.00-15.656-7.35-30.812-20.695-42.676C 283.834,167.573, 262.771,160.00, 240.00,160.00c-22.772,0.00-43.834,7.573-59.304,21.324 + C 167.35,193.188, 160.00,208.344, 160.00,224.00L 160.00,416.00 L 96.00,416.00 l0.00-192.00 c0.00-70.691, 64.471-128.00, 144.00-128.00c 79.529,0.00, 144.00,57.309, 144.00,128.00L 384.00,416.00 L 320.00,416.00 z" /> +<glyph unicode="" d="M 416.00,416.00l0.00-32.00 l-72.00,0.00 L 216.00,64.00l 72.00,0.00 l0.00-32.00 L 64.00,32.00 l0.00,32.00 l 72.00,0.00 L 264.00,384.00l-72.00,0.00 L 192.00,416.00 L 416.00,416.00 z" /> +<glyph unicode="" d="M 312.721,232.909C 336.758,251.984, 352.00,280.337, 352.00,312.00c0.00,57.438-50.145,104.00-112.00,104.00L 128.00,416.00 l0.00-384.00 l 144.00,0.00 + c 61.856,0.00, 112.00,46.562, 112.00,104.00C 384.00,180.098, 354.441,217.781, 312.721,232.909z M 192.00,328.00c0.00,13.255, 10.745,24.00, 24.00,24.00l 33.602,0.00 + C 270.809,352.00, 288.00,330.51, 288.00,304.00s-17.191-48.00-38.398-48.00L 192.00,256.00 L 192.00,328.00 z M 273.60,96.00L 216.00,96.00 c-13.255,0.00-24.00,10.745-24.00,24.00l0.00,72.00 l 81.60,0.00 + c 21.209,0.00, 38.40-21.49, 38.40-48.00S 294.809,96.00, 273.60,96.00z" /> +<glyph unicode="" d="M 425.373,358.627l-66.746,66.745C 346.183,437.818, 321.60,448.00, 304.00,448.00L 96.00,448.00 c-17.60,0.00-32.00-14.40-32.00-32.00l0.00-384.00 c0.00-17.60, 14.40-32.00, 32.00-32.00l 320.00,0.00 + c 17.60,0.00, 32.00,14.40, 32.00,32.00L 448.00,304.00 C 448.00,321.60, 437.817,346.182, 425.373,358.627z M 402.745,336.001c 3.396-3.398, 6.896-9.581, 9.447-16.001L 320.00,320.00 + L 320.00,412.193 c 6.42-2.55, 12.602-6.05, 16.00-9.448L 402.745,336.001z M 415.942,32.00L 96.057,32.00 c-0.02,0.017-0.041,0.038-0.057,0.058L 96.00,415.943 + c 0.017,0.02, 0.038,0.041, 0.057,0.057L 288.00,416.00 l0.00-128.00 l 128.00,0.00 l0.00-255.942 C 415.983,32.038, 415.962,32.017, 415.942,32.00z" /> +<glyph unicode="" d="M 480.00,40.00L 480.00,335.969 L 368.031,448.00L 72.00,448.00 c-22.091,0.00-40.00-17.908-40.00-40.00l0.00-368.00 c0.00-22.092, 17.909-40.00, 40.00-40.00l 368.00,0.00 + C 462.092,0.00, 480.00,17.908, 480.00,40.00z M 288.00,384.00l 32.00,0.00 l0.00-96.00 l-32.00,0.00 L 288.00,384.00 z M 352.00,64.00L 160.00,64.00 L 160.00,191.941 c 0.017,0.021, 0.038,0.041, 0.058,0.059l 191.885,0.00 + c 0.02-0.018, 0.041-0.038, 0.058-0.059L 352.00,64.00L 352.00,64.00z M 416.00,64.00l-32.00,0.00 L 384.00,192.00 c0.00,17.60-14.40,32.00-32.00,32.00L 160.00,224.00 c-17.60,0.00-32.00-14.40-32.00-32.00l0.00-128.00 L 96.00,64.00 L 96.00,384.00 + l 32.00,0.00 l0.00-96.00 c0.00-17.60, 14.40-32.00, 32.00-32.00l 160.00,0.00 c 17.60,0.00, 32.00,14.40, 32.00,32.00l0.00,85.505 l 64.00-64.036L 416.00,64.00 z" /> +<glyph unicode="" d="M 32.00,384.00l0.00-352.00 l 448.00,0.00 L 480.00,384.00 L 32.00,384.00 z M 192.00,160.00l0.00,64.00 l 128.00,0.00 l0.00-64.00 L 192.00,160.00 z M 320.00,128.00l0.00-64.00 L 192.00,64.00 l0.00,64.00 L 320.00,128.00 z M 320.00,320.00l0.00-64.00 L 192.00,256.00 l0.00,64.00 L 320.00,320.00 z M 160.00,320.00l0.00-64.00 L 64.00,256.00 l0.00,64.00 L 160.00,320.00 + z M 64.00,224.00l 96.00,0.00 l0.00-64.00 L 64.00,160.00 L 64.00,224.00 z M 352.00,224.00l 96.00,0.00 l0.00-64.00 l-96.00,0.00 L 352.00,224.00 z M 352.00,256.00l0.00,64.00 l 96.00,0.00 l0.00-64.00 L 352.00,256.00 z M 64.00,128.00l 96.00,0.00 l0.00-64.00 L 64.00,64.00 L 64.00,128.00 z M 352.00,64.00l0.00,64.00 l 96.00,0.00 l0.00-64.00 L 352.00,64.00 z" /> +<glyph unicode="" d="M 256.00,410.00c 49.683,0.00, 96.391-19.347, 131.521-54.478S 442.00,273.683, 442.00,224.00s-19.348-96.391-54.479-131.521S 305.683,38.00, 256.00,38.00 + s-96.391,19.348-131.522,54.479S 70.00,174.317, 70.00,224.00s 19.347,96.391, 54.478,131.522S 206.317,410.00, 256.00,410.00 M 256.00,448.00 + C 132.288,448.00, 32.00,347.712, 32.00,224.00s 100.288-224.00, 224.00-224.00s 224.00,100.288, 224.00,224.00S 379.712,448.00, 256.00,448.00L 256.00,448.00zM 160.00,288.00A32.00,32.00 1620.00 1 1 224.00,288A32.00,32.00 1620.00 1 1 160.00,288zM 288.00,288.00A32.00,32.00 1620.00 1 1 352.00,288A32.00,32.00 1620.00 1 1 288.00,288zM 256.00,152.00c-50.92,0.00-96.28,18.437-125.583,47.164C 141.98,140.36, 193.806,96.00, 256.00,96.00c 62.194,0.00, 114.02,44.36, 125.584,103.164 + C 352.28,170.437, 306.92,152.00, 256.00,152.00z" /> +<glyph unicode="" d="M 240.00,288.00L 144.00,384.00L 208.00,448.00L 32.00,448.00L 32.00,272.00L 96.00,336.00L 192.00,240.00 zM 320.00,240.00L 416.00,336.00L 480.00,272.00L 480.00,448.00L 304.00,448.00L 368.00,384.00L 272.00,288.00 zM 272.00,160.00L 368.00,64.00L 304.00,0.00L 480.00,0.00L 480.00,176.00L 416.00,112.00L 320.00,208.00 zM 192.00,208.00L 96.00,112.00L 32.00,176.00L 32.00,0.00L 208.00,0.00L 144.00,64.00L 240.00,160.00 z" /> +<glyph unicode="" d="M 32.00,256.00L 480.00,256.00L 480.00,192.00L 32.00,192.00z" /> +<glyph unicode="" d="M 32.00,96.00l 256.00,0.00 l0.00-64.00 L 32.00,32.00 L 32.00,96.00 z M 384.00,384.00L 273.721,384.00 l-91.883-256.00l-66.144,0.00 l 91.881,256.00L 96.00,384.00 L 96.00,448.00 l 288.00,0.00 L 384.00,384.00 z M 464.887,32.00L 400.00,96.887 + L 335.113,32.00L 304.00,63.113L 368.887,128.00L 304.00,192.887L 335.113,224.00L 400.00,159.113L 464.887,224.00L 496.00,192.887L 431.113,128.00L 496.00,63.113 + L 464.887,32.00z" /> +<glyph unicode="" d="M 128.00,416.00l 256.00,0.00 l0.00-64.00 L 128.00,352.00 L 128.00,416.00 z M 448.00,320.00L 64.00,320.00 c-17.60,0.00-32.00-14.40-32.00-32.00l0.00-128.00 c0.00-17.60, 14.398-32.00, 32.00-32.00l 64.00,0.00 l0.00-96.00 l 256.00,0.00 l0.00,96.00 l 64.00,0.00 + c 17.60,0.00, 32.00,14.40, 32.00,32.00L 480.00,288.00 C 480.00,305.60, 465.60,320.00, 448.00,320.00z M 352.00,64.00L 160.00,64.00 L 160.00,192.00 l 192.00,0.00 L 352.00,64.00 z M 455.20,272.00c0.00-12.813-10.387-23.20-23.199-23.20 + S 408.80,259.187, 408.80,272.00s 10.389,23.20, 23.201,23.20C 444.814,295.20, 455.20,284.813, 455.20,272.00z" /> +<glyph unicode="" d="M 192.00,416.00c-61.856,0.00-112.00-50.144-112.00-112.00s 50.144-112.00, 112.00-112.00l0.00-160.00 l 64.00,0.00 L 256.00,352.00 l 32.00,0.00 l0.00-320.00 l 64.00,0.00 L 352.00,352.00 l 64.00,0.00 L 416.00,416.00 L 192.00,416.00 z" /> +<glyph unicode="" d="M 224.00,416.00c-61.856,0.00-112.00-50.144-112.00-112.00s 50.144-112.00, 112.00-112.00l0.00-160.00 l 64.00,0.00 L 288.00,352.00 l 32.00,0.00 l0.00-320.00 l 64.00,0.00 L 384.00,352.00 l 64.00,0.00 L 448.00,416.00 L 224.00,416.00 zM 32.00,32.00L 144.00,128.00L 32.00,224.00 z" /> +<glyph unicode="" d="M 160.00,416.00C 98.144,416.00, 48.00,365.856, 48.00,304.00s 50.144-112.00, 112.00-112.00l0.00-160.00 l 64.00,0.00 L 224.00,352.00 l 32.00,0.00 l0.00-320.00 l 64.00,0.00 L 320.00,352.00 l 64.00,0.00 L 384.00,416.00 L 160.00,416.00 zM 480.00,224.00L 368.00,128.00L 480.00,32.00 z" /> +<glyph unicode="" d="M 256.00,288.00L 320.00,288.00L 320.00,256.00L 256.00,256.00zM 256.00,96.00L 320.00,96.00L 320.00,64.00L 256.00,64.00zM 288.00,192.00L 352.00,192.00L 352.00,160.00L 288.00,160.00zM 384.00,192.00L 384.00,96.00L 352.00,96.00L 352.00,64.00L 416.00,64.00L 416.00,192.00 zM 192.00,192.00L 256.00,192.00L 256.00,160.00L 192.00,160.00zM 160.00,96.00L 224.00,96.00L 224.00,64.00L 160.00,64.00zM 160.00,288.00L 224.00,288.00L 224.00,256.00L 160.00,256.00zM 96.00,384.00L 96.00,256.00L 128.00,256.00L 128.00,352.00L 160.00,352.00L 160.00,384.00 zM 352.00,256.00L 416.00,256.00L 416.00,384.00L 384.00,384.00L 384.00,288.00L 352.00,288.00 zM 32.00,448.00l0.00-448.00 l 448.00,0.00 L 480.00,448.00 L 32.00,448.00 z M 448.00,32.00L 64.00,32.00 L 64.00,416.00 l 384.00,0.00 L 448.00,32.00 zM 96.00,192.00L 96.00,64.00L 128.00,64.00L 128.00,160.00L 160.00,160.00L 160.00,192.00 zM 288.00,384.00L 352.00,384.00L 352.00,352.00L 288.00,352.00zM 192.00,384.00L 256.00,384.00L 256.00,352.00L 192.00,352.00z" /> +<glyph unicode="" d="M 408.00,448.00l 8.00-192.00L 96.00,256.00 l 8.00,192.00l 16.00,0.00 l 8.00-160.00l 256.00,0.00 l 8.00,160.00L 408.00,448.00 z M 104.00,0.00l-8.00,160.00l 320.00,0.00 l-8.00-160.00l-16.00,0.00 l-8.00,128.00L 128.00,128.00 l-8.00-128.00L 104.00,0.00 zM 32.00,224.00L 96.00,224.00L 96.00,192.00L 32.00,192.00zM 128.00,224.00L 192.00,224.00L 192.00,192.00L 128.00,192.00zM 224.00,224.00L 288.00,224.00L 288.00,192.00L 224.00,192.00zM 320.00,224.00L 384.00,224.00L 384.00,192.00L 320.00,192.00zM 416.00,224.00L 480.00,224.00L 480.00,192.00L 416.00,192.00z" /> +<glyph unicode="" d="M 480.00,416.00L 480.00,448.00 l-96.00,0.00 c-17.601,0.00-32.00-14.40-32.00-32.00l0.00-160.00 c0.00-7.928, 2.929-15.201, 7.748-20.807L 208.00,105.00l-71.00,74.00l-41.00-35.00l 112.00-144.00l 208.00,224.00l 64.00,0.00 + l0.00,32.00 l-96.00,0.00 L 384.00,416.00 L 480.00,416.00 zM 128.00,224.00l 32.00,0.00 L 160.00,416.00 c0.00,17.60-14.40,32.00-32.00,32.00L 64.00,448.00 c-17.60,0.00-32.00-14.40-32.00-32.00l0.00-192.00 l 32.00,0.00 l0.00,96.00 l 64.00,0.00 L 128.00,224.00 z M 64.00,352.00L 64.00,416.00 l 64.00,0.00 l0.00-64.00 L 64.00,352.00 zM 320.00,256.00l0.00,48.00 c0.00,17.60-4.40,32.00-22.00,32.00c 17.60,0.00, 22.00,14.40, 22.00,32.00L 320.00,416.00 c0.00,17.60-14.40,32.00-32.00,32.00l-96.00,0.00 l0.00-224.00 l 96.00,0.00 C 305.60,224.00, 320.00,238.40, 320.00,256.00z + M 224.00,416.00l 64.00,0.00 l0.00-64.00 l-64.00,0.00 L 224.00,416.00 z M 224.00,320.00l 64.00,0.00 l0.00-64.00 l-64.00,0.00 L 224.00,320.00 z" /> +<glyph unicode="" d="M 224.00,224.00l-64.00,0.00 l0.00,64.00 l 64.00,0.00 l0.00,64.00 l 64.00,0.00 l0.00-64.00 l 64.00,0.00 l0.00-64.00 l-64.00,0.00 l0.00-64.00 l-64.00,0.00 L 224.00,224.00 z M 480.00,192.00l0.00-160.00 L 32.00,32.00 L 32.00,192.00 l 64.00,0.00 l0.00-96.00 l 320.00,0.00 l0.00,96.00 L 480.00,192.00 z" /> +<glyph unicode="" d="M 208.00,128.00L 112.00,224.00L 208.00,320.00L 176.00,352.00L 48.00,224.00L 176.00,96.00 zM 336.00,352.00L 304.00,320.00L 400.00,224.00L 304.00,128.00L 336.00,96.00L 464.00,224.00 z" /> +<glyph unicode="" d="M 224.00,128.00l 64.00,0.00 l0.00-64.00 l-64.00,0.00 L 224.00,128.00 z M 352.00,352.00c 17.673,0.00, 32.00-14.327, 32.00-32.00l0.00-83.00 l-114.00-77.00l-46.00,0.00 l0.00,32.00 l 96.00,64.00l0.00,32.00 L 160.00,288.00 l0.00,64.00 L 352.00,352.00 z M 256.00,448.00 + c-59.833,0.00-116.083-23.30-158.392-65.608C 55.301,340.083, 32.00,283.833, 32.00,224.00c0.00-59.832, 23.301-116.084, 65.608-158.392 + C 139.917,23.30, 196.167,0.00, 256.00,0.00c 59.832,0.00, 116.084,23.30, 158.392,65.608C 456.70,107.916, 480.00,164.168, 480.00,224.00 + c0.00,59.833-23.30,116.083-65.608,158.392C 372.084,424.70, 315.832,448.00, 256.00,448.00z" /> +<glyph unicode="" d="M 448.00,416.00L 64.00,416.00 c-17.60,0.00-32.00-14.40-32.00-32.00l0.00-320.00 c0.00-17.60, 14.40-32.00, 32.00-32.00l 384.00,0.00 c 17.60,0.00, 32.00,14.40, 32.00,32.00L 480.00,384.00 C 480.00,401.60, 465.60,416.00, 448.00,416.00z + M 448.00,64.058c-0.006-0.007-0.015-0.014-0.021-0.021L 352.00,224.00l-80.00-64.00L 160.00,304.00L 64.016,64.042c-0.005,0.005-0.011,0.011-0.016,0.016 + L 64.00,383.943 c 0.017,0.02, 0.038,0.041, 0.057,0.057l 383.885,0.00 c 0.02-0.017, 0.041-0.038, 0.058-0.058L 448.00,64.058 zM 320.00,304.00A48.00,48.00 1620.00 1 1 416.00,304A48.00,48.00 1620.00 1 1 320.00,304z" /> +<glyph unicode="" d="M 448.00,416.00L 64.00,416.00 c-17.60,0.00-32.00-14.40-32.00-32.00l0.00-320.00 c0.00-17.60, 14.40-32.00, 32.00-32.00l 384.00,0.00 c 17.60,0.00, 32.00,14.40, 32.00,32.00L 480.00,384.00 C 480.00,401.60, 465.60,416.00, 448.00,416.00z + M 128.00,64.00L 64.00,64.00 l0.00,64.00 l 64.00,0.00 L 128.00,64.00 z M 128.00,192.00L 64.00,192.00 l0.00,64.00 l 64.00,0.00 L 128.00,192.00 z M 128.00,320.00L 64.00,320.00 L 64.00,384.00 l 64.00,0.00 L 128.00,320.00 z M 352.00,64.00L 160.00,64.00 L 160.00,384.00 l 192.00,0.00 L 352.00,64.00 z M 448.00,64.00l-64.00,0.00 l0.00,64.00 l 64.00,0.00 L 448.00,64.00 z + M 448.00,192.00l-64.00,0.00 l0.00,64.00 l 64.00,0.00 L 448.00,192.00 z M 448.00,320.00l-64.00,0.00 L 384.00,384.00 l 64.00,0.00 L 448.00,320.00 zM 192.00,320.00L 192.00,128.00L 336.00,224.00 z" /> +<glyph unicode="" d="M 38.899,327.688l 40.707-25.441C 105.007,342.804, 144.00,373.974, 190.21,389.37l-15.183,45.547 + C 118.153,415.968, 70.163,377.604, 38.899,327.688zM 336.973,434.917L 321.79,389.37c 46.211-15.396, 85.202-46.566, 110.604-87.124l 40.706,25.441 + C 441.837,377.604, 393.847,415.968, 336.973,434.917zM 303.987,127.996c-2.404,0.00-4.846,0.545-7.143,1.693L 224.00,166.111L 224.00,272.00 c0.00,8.836, 7.164,16.00, 16.00,16.00s 16.00-7.164, 16.00-16.00l0.00-86.111 + l 55.155-27.578c 7.903-3.951, 11.107-13.562, 7.155-21.466C 315.508,131.238, 309.856,127.997, 303.987,127.996zM 256.00,384.00C 149.961,384.00, 64.00,298.039, 64.00,192.00c0.00-106.039, 85.961-192.00, 192.00-192.00c 106.039,0.00, 192.00,85.961, 192.00,192.00 + C 448.00,298.039, 362.039,384.00, 256.00,384.00z M 256.00,48.00c-79.529,0.00-144.00,64.471-144.00,144.00c0.00,79.529, 64.471,144.00, 144.00,144.00c 79.529,0.00, 144.00-64.471, 144.00-144.00 + C 400.00,112.471, 335.529,48.00, 256.00,48.00z" /> +<glyph unicode="" d="M 32.00,252.127c 22.659,24.96, 48.581,46.18, 76.636,62.562C 153.802,341.061, 204.759,355.00, 256.00,355.00 + c 51.24,0.00, 102.198-13.939, 147.363-40.312c 28.056-16.382, 53.978-37.602, 76.637-62.562l0.00,58.716 + c-16.505,14.059-34.062,26.57-52.434,37.297C 375.063,378.796, 315.737,395.00, 256.00,395.00s-119.064-16.204-171.567-46.86 + C 66.062,337.413, 48.505,324.901, 32.00,310.842L 32.00,252.127 zM 256.00,320.00c-91.598,0.00-172.919-50.278-224.00-128.00c 51.081-77.724, 132.402-128.00, 224.00-128.00c 91.598,0.00, 172.919,50.276, 224.00,128.00 + C 428.919,269.722, 347.598,320.00, 256.00,320.00z M 256.00,224.00c0.00-17.673-14.327-32.00-32.00-32.00s-32.00,14.327-32.00,32.00c0.00,17.674, 14.327,32.00, 32.00,32.00 + S 256.00,241.674, 256.00,224.00z M 364.033,131.669C 330.316,111.982, 293.969,102.00, 256.00,102.00s-74.316,9.982-108.033,29.669 + C 122.19,146.721, 98.659,167.324, 78.91,192.00c 19.749,24.675, 43.28,45.279, 69.058,60.33c 6.638,3.876, 13.379,7.37, 20.213,10.491 + C 162.925,250.95, 160.00,237.817, 160.00,224.00c0.00-53.02, 42.981-96.00, 96.00-96.00c 53.02,0.00, 96.00,42.98, 96.00,96.00c0.00,13.817-2.925,26.95-8.18,38.821 + c 6.834-3.122, 13.575-6.615, 20.213-10.491c 25.777-15.051, 49.308-35.655, 69.058-60.33 + C 413.342,167.324, 389.811,146.721, 364.033,131.669z" /> +<glyph unicode="" d="M 325.584,338.083C 313.278,379.064, 311.146,384.00, 272.00,384.00l-32.00,0.00 c-39.809,0.00-41.332-5.076-54.209-48.00c0.00-0.001,0.00-0.001-0.001-0.002 + L 113.791,96.00l 56.818,0.00 l 28.80,96.00l 113.183,0.00 l 28.80-96.00l 56.815,0.00 L 325.584,338.083z M 218.609,256.00l 19.20,68.00c 5.043,16.809, 18.19,15.00, 18.19,15.00 + s 13.147,1.809, 18.19-15.00l 0.002,0.00 l 19.20-68.00L 218.609,256.00 z" /> +<glyph unicode="" d="M 288.00,448.00 C 411.712,448.00 512.00,347.712 512.00,224.00 C 512.00,100.288 411.712,0.00 288.00,0.00 L 288.00,48.00 C 335.012,48.00 379.209,66.307 412.451,99.549 C 445.693,132.791 464.00,176.988 464.00,224.00 C 464.00,271.011 445.693,315.209 412.451,348.451 C 379.209,381.693 335.012,400.00 288.00,400.00 C 240.989,400.00 196.791,381.693 163.549,348.451 C 137.979,322.882 121.258,290.828 114.896,256.00 L 208.00,256.00 L 96.00,128.00 L -16.00,256.00 L 66.285,256.00 C 81.815,364.551 175.154,448.00 288.00,448.00 ZM 384.00,256.00 L 384.00,192.00 L 256.00,192.00 L 256.00,352.00 L 320.00,352.00 L 320.00,256.00 Z" /> +<glyph unicode="" d="M 512.00,183.771l0.00,80.458 l-79.572,7.957c-4.093,15.021-10.044,29.274-17.605,42.49l 52.298,63.919L 410.595,435.12l-63.918-52.298 + c-13.217,7.562-27.471,13.513-42.491,17.604L 296.229,480.00l-80.458,0.00 l-7.957-79.573c-15.021-4.093-29.274-10.043-42.49-17.604 + L 101.405,435.12L 44.88,378.595l 52.298-63.918c-7.562-13.216-13.513-27.47-17.605-42.49L0.00,264.229l0.00-80.458 l 79.573-7.957 + c 4.093-15.021, 10.043-29.274, 17.605-42.491L 44.88,69.405l 56.524-56.524l 63.919,52.298c 13.216-7.562, 27.47-13.514, 42.49-17.605 + L 215.771-32.00l 80.458,0.00 l 7.957,79.572c 15.021,4.093, 29.274,10.044, 42.491,17.605l 63.918-52.298l 56.524,56.524l-52.298,63.918 + c 7.562,13.217, 13.514,27.471, 17.605,42.49L 512.00,183.771z M 352.00,192.00l-64.00-64.00l-64.00,0.00 l-64.00,64.00l0.00,64.00 l 64.00,64.00l 64.00,0.00 l 64.00-64.00L 352.00,192.00 z" /> +<glyph unicode="" d="M 384.00,377.00 L 384.00,352.00 L 448.00,352.00 L 448.00,320.00 L 352.00,320.00 L 352.00,393.00 L 416.00,423.00 L 416.00,448.00 L 352.00,448.00 L 352.00,480.00 L 448.00,480.00 L 448.00,407.00 ZM 338.00,352.00L 270.00,352.00L 176.00,258.00L 82.00,352.00L 14.00,352.00L 142.00,224.00L 14.00,96.00L 82.00,96.00L 176.00,190.00L 270.00,96.00L 338.00,96.00L 210.00,224.00 z" /> +<glyph unicode="" d="M 384.00,25.00 L 384.00,0.00 L 448.00,0.00 L 448.00-32.00 L 352.00-32.00 L 352.00,41.00 L 416.00,71.00 L 416.00,96.00 L 352.00,96.00 L 352.00,128.00 L 448.00,128.00 L 448.00,55.00 ZM 338.00,352.00L 270.00,352.00L 176.00,258.00L 82.00,352.00L 14.00,352.00L 142.00,224.00L 14.00,96.00L 82.00,96.00L 176.00,190.00L 270.00,96.00L 338.00,96.00L 210.00,224.00 z" /> +<glyph unicode=" " horiz-adv-x="256" /> +<glyph class="hidden" unicode="" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" /> +</font></defs></svg>
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.ttf b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.ttf Binary files differnew file mode 100644 index 00000000..8fad6572 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.ttf diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.woff b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.woff Binary files differnew file mode 100644 index 00000000..e5f89435 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon-small.woff diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.eot b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.eot Binary files differnew file mode 100644 index 00000000..0350809a --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.eot diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.svg b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.svg new file mode 100644 index 00000000..fa1d05f6 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.svg @@ -0,0 +1,150 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata> +This is a custom SVG font generated by IcoMoon. +<iconset grid="16"></iconset> +</metadata> +<defs> +<font id="icomoon" horiz-adv-x="512" > +<font-face units-per-em="512" ascent="480" descent="-32" /> +<missing-glyph horiz-adv-x="512" /> +<glyph unicode="" d="M 464.00,416.00L 256.00,416.00L 240.00,448.00L 64.00,448.00L 32.00,384.00L 480.00,384.00 zM 452.17,128.00l 37.43,0.00 L 512.00,352.00L0.00,352.00 l 32.00-320.00l 242.04,0.00 C 221.599,50.888, 184.00,101.133, 184.00,160.00c0.00,74.991, 61.009,136.00, 136.00,136.00 + c 74.99,0.00, 136.00-61.009, 136.00-136.00C 456.00,149.161, 454.689,138.425, 452.17,128.00zM 501.498,23.125l-99.248,87.346C 410.977,124.931, 416.00,141.878, 416.00,160.00c0.00,53.02-42.98,96.00-96.00,96.00s-96.00-42.98-96.00-96.00 + s 42.98-96.00, 96.00-96.00c 18.122,0.00, 35.069,5.023, 49.529,13.75l 87.346-99.248c 11.481-13.339, 31.059-14.07, 43.503-1.626l 2.746,2.746 + C 515.568-7.934, 514.837,11.644, 501.498,23.125z M 320.00,98.00c-34.242,0.00-62.00,27.758-62.00,62.00s 27.758,62.00, 62.00,62.00s 62.00-27.758, 62.00-62.00 + S 354.242,98.00, 320.00,98.00z" /> +<glyph unicode="" d="M 384.00,352.00L 416.00,352.00L 416.00,320.00L 384.00,320.00zM 320.00,288.00L 352.00,288.00L 352.00,256.00L 320.00,256.00zM 320.00,224.00L 352.00,224.00L 352.00,192.00L 320.00,192.00zM 320.00,160.00L 352.00,160.00L 352.00,128.00L 320.00,128.00zM 256.00,224.00L 288.00,224.00L 288.00,192.00L 256.00,192.00zM 256.00,160.00L 288.00,160.00L 288.00,128.00L 256.00,128.00zM 192.00,160.00L 224.00,160.00L 224.00,128.00L 192.00,128.00zM 384.00,288.00L 416.00,288.00L 416.00,256.00L 384.00,256.00zM 384.00,224.00L 416.00,224.00L 416.00,192.00L 384.00,192.00zM 384.00,160.00L 416.00,160.00L 416.00,128.00L 384.00,128.00zM 384.00,96.00L 416.00,96.00L 416.00,64.00L 384.00,64.00zM 320.00,96.00L 352.00,96.00L 352.00,64.00L 320.00,64.00zM 256.00,96.00L 288.00,96.00L 288.00,64.00L 256.00,64.00zM 192.00,96.00L 224.00,96.00L 224.00,64.00L 192.00,64.00zM 128.00,96.00L 160.00,96.00L 160.00,64.00L 128.00,64.00z" /> +<glyph unicode="" d="M 416.00,352.00l-96.00,0.00 L 320.00,384.00 L 224.00,480.00L0.00,480.00 l0.00-384.00 l 192.00,0.00 l0.00-128.00 l 320.00,0.00 L 512.00,256.00 L 416.00,352.00z M 416.00,306.745L 466.745,256.00L 416.00,256.00 L 416.00,306.745 z M 224.00,434.745L 274.745,384.00L 224.00,384.00 + L 224.00,434.745 z M 32.00,448.00l 160.00,0.00 l0.00-96.00 l 96.00,0.00 l0.00-224.00 L 32.00,128.00 L 32.00,448.00 z M 480.00,0.00L 224.00,0.00 l0.00,96.00 l 96.00,0.00 L 320.00,320.00 l 64.00,0.00 l0.00-96.00 l 96.00,0.00 L 480.00,0.00 z" /> +<glyph unicode="" d="M 128.00,448.00 L 384.00,448.00 L 384.00,384.00 L 320.00,384.00 L 320.00,0.00 L 256.00,0.00 L 256.00,384.00 L 192.00,384.00 L 192.00,0.00 L 128.00,0.00 L 128.00,224.00 C 66.144,224.00 16.00,274.144 16.00,336.00 C 16.00,397.856 66.144,448.00 128.00,448.00 ZM 480.00,32.00L 352.00,144.00L 480.00,256.00 z" /> +<glyph unicode="" d="M 224.00,448.00 L 480.00,448.00 L 480.00,384.00 L 416.00,384.00 L 416.00,0.00 L 352.00,0.00 L 352.00,384.00 L 288.00,384.00 L 288.00,0.00 L 224.00,0.00 L 224.00,224.00 C 162.144,224.00 112.00,274.144 112.00,336.00 C 112.00,397.856 162.144,448.00 224.00,448.00 ZM 32.00,256.00L 160.00,144.00L 32.00,32.00 z" /> +<glyph unicode="" d="M 192.00,448.00 L 448.00,448.00 L 448.00,384.00 L 384.00,384.00 L 384.00,0.00 L 320.00,0.00 L 320.00,384.00 L 256.00,384.00 L 256.00,0.00 L 192.00,0.00 L 192.00,224.00 C 130.144,224.00 80.00,274.144 80.00,336.00 C 80.00,397.856 130.144,448.00 192.00,448.00 Z" /> +<glyph unicode="" d="M 365.71,221.482 C 397.67,197.513 416.00,163.439 416.00,128.00 C 416.00,92.561 397.67,58.487 365.71,34.518 C 336.031,12.259 297.068,0.00 256.00,0.00 C 214.931,0.00 175.969,12.259 146.29,34.518 C 114.33,58.487 96.00,92.561 96.00,128.00 L 160.00,128.00 C 160.00,93.309 203.963,64.00 256.00,64.00 C 308.037,64.00 352.00,93.309 352.00,128.00 C 352.00,162.691 308.037,192.00 256.00,192.00 C 214.931,192.00 175.969,204.259 146.29,226.518 C 114.33,250.488 96.00,284.561 96.00,320.00 C 96.00,355.439 114.33,389.512 146.29,413.482 C 175.969,435.741 214.931,448.00 256.00,448.00 C 297.068,448.00 336.031,435.741 365.71,413.482 C 397.67,389.512 416.00,355.439 416.00,320.00 L 352.00,320.00 C 352.00,354.691 308.037,384.00 256.00,384.00 C 203.963,384.00 160.00,354.691 160.00,320.00 C 160.00,285.309 203.963,256.00 256.00,256.00 C 297.068,256.00 336.031,243.741 365.71,221.482 ZM0.00,224.00L 512.00,224.00L 512.00,192.00L0.00,192.00z" /> +<glyph unicode="" d="M 352.00,448.00 L 416.00,448.00 L 416.00,240.00 C 416.00,160.471 344.366,96.00 256.00,96.00 C 167.635,96.00 96.00,160.471 96.00,240.00 L 96.00,448.00 L 160.00,448.00 L 160.00,240.00 C 160.00,219.917 169.119,200.648 185.677,185.747 C 204.125,169.145 229.10,160.00 256.00,160.00 C 282.90,160.00 307.875,169.145 326.323,185.747 C 342.881,200.648 352.00,219.917 352.00,240.00 L 352.00,448.00 ZM 96.00,64.00L 416.00,64.00L 416.00,0.00L 96.00,0.00z" /> +<glyph unicode="" d="M 448.00,448.00 L 448.00,416.00 L 384.00,416.00 L 224.00,32.00 L 288.00,32.00 L 288.00,0.00 L 64.00,0.00 L 64.00,32.00 L 128.00,32.00 L 288.00,416.00 L 224.00,416.00 L 224.00,448.00 Z" /> +<glyph unicode="" d="M 353.94,237.674C 372.689,259.945, 384.00,288.678, 384.00,320.00c0.00,70.58-57.421,128.00-128.00,128.00l-64.00,0.00 l-64.00,0.00 L 96.00,448.00 l0.00-448.00 l 32.00,0.00 l 64.00,0.00 l 96.00,0.00 + c 70.579,0.00, 128.00,57.421, 128.00,128.00C 416.00,174.478, 391.101,215.248, 353.94,237.674z M 192.00,384.00l 50.75,0.00 c 27.984,0.00, 50.75-28.71, 50.75-64.00 + s-22.766-64.00-50.75-64.00L 192.00,256.00 L 192.00,384.00 z M 271.50,64.00L 192.00,64.00 L 192.00,192.00 l 79.50,0.00 c 29.225,0.00, 53.00-28.71, 53.00-64.00S 300.725,64.00, 271.50,64.00z" /> +<glyph unicode="" d="M 192.00,64.00L 288.00,64.00L 288.00-32.00L 192.00-32.00zM 400.00,448.00 C 426.51,448.00 448.00,426.51 448.00,400.00 L 448.00,256.00 L 288.00,160.00 L 288.00,96.00 L 192.00,96.00 L 192.00,192.00 L 352.00,288.00 L 352.00,352.00 L 96.00,352.00 L 96.00,448.00 L 400.00,448.00 Z" /> +<glyph unicode="" d="M 288.00,448.00 C 411.712,448.00 512.00,347.712 512.00,224.00 C 512.00,100.288 411.712,0.00 288.00,0.00 L 288.00,48.00 C 335.012,48.00 379.209,66.307 412.451,99.549 C 445.693,132.791 464.00,176.988 464.00,224.00 C 464.00,271.011 445.693,315.209 412.451,348.451 C 379.209,381.693 335.012,400.00 288.00,400.00 C 240.989,400.00 196.791,381.693 163.549,348.451 C 137.979,322.882 121.258,290.828 114.896,256.00 L 208.00,256.00 L 96.00,128.00 L -16.00,256.00 L 66.285,256.00 C 81.815,364.551 175.154,448.00 288.00,448.00 ZM 384.00,256.00 L 384.00,192.00 L 256.00,192.00 L 256.00,352.00 L 320.00,352.00 L 320.00,256.00 Z" /> +<glyph unicode="" d="M0.00,224.00L 64.00,224.00L 64.00,192.00L0.00,192.00zM 96.00,224.00L 192.00,224.00L 192.00,192.00L 96.00,192.00zM 224.00,224.00L 288.00,224.00L 288.00,192.00L 224.00,192.00zM 320.00,224.00L 416.00,224.00L 416.00,192.00L 320.00,192.00zM 448.00,224.00L 512.00,224.00L 512.00,192.00L 448.00,192.00zM 440.00,480.00 L 448.00,256.00 L 64.00,256.00 L 72.00,480.00 L 88.00,480.00 L 96.00,288.00 L 416.00,288.00 L 424.00,480.00 ZM 72.00-32.00 L 64.00,160.00 L 448.00,160.00 L 440.00-32.00 L 424.00-32.00 L 416.00,128.00 L 96.00,128.00 L 88.00-32.00 Z" /> +<glyph unicode="" d="M 192.00,384.00L 256.00,384.00L 256.00,352.00L 192.00,352.00zM 288.00,384.00L 352.00,384.00L 352.00,352.00L 288.00,352.00zM 448.00,384.00 L 448.00,256.00 L 352.00,256.00 L 352.00,288.00 L 416.00,288.00 L 416.00,352.00 L 384.00,352.00 L 384.00,384.00 ZM 160.00,288.00L 224.00,288.00L 224.00,256.00L 160.00,256.00zM 256.00,288.00L 320.00,288.00L 320.00,256.00L 256.00,256.00zM 96.00,352.00 L 96.00,288.00 L 128.00,288.00 L 128.00,256.00 L 64.00,256.00 L 64.00,384.00 L 160.00,384.00 L 160.00,352.00 ZM 192.00,192.00L 256.00,192.00L 256.00,160.00L 192.00,160.00zM 288.00,192.00L 352.00,192.00L 352.00,160.00L 288.00,160.00zM 448.00,192.00 L 448.00,64.00 L 352.00,64.00 L 352.00,96.00 L 416.00,96.00 L 416.00,160.00 L 384.00,160.00 L 384.00,192.00 ZM 160.00,96.00L 224.00,96.00L 224.00,64.00L 160.00,64.00zM 256.00,96.00L 320.00,96.00L 320.00,64.00L 256.00,64.00zM 96.00,160.00 L 96.00,96.00 L 128.00,96.00 L 128.00,64.00 L 64.00,64.00 L 64.00,192.00 L 160.00,192.00 L 160.00,160.00 ZM 480.00,448.00 L 32.00,448.00 L 32.00,0.00 L 480.00,0.00 L 480.00,448.00 Z M 512.00,480.00 L 512.00,480.00 L 512.00-32.00 L 0.00-32.00 L 0.00,480.00 L 512.00,480.00 Z" /> +<glyph unicode="" d="M 224.00,192.00 L 128.00,192.00 L 128.00,256.00 L 224.00,256.00 L 224.00,352.00 L 288.00,352.00 L 288.00,256.00 L 384.00,256.00 L 384.00,192.00 L 288.00,192.00 L 288.00,96.00 L 224.00,96.00 ZM 512.00,160.00 L 512.00-32.00 L 0.00-32.00 L 0.00,160.00 L 64.00,160.00 L 64.00,32.00 L 448.00,32.00 L 448.00,160.00 Z" /> +<glyph unicode="" d="M 64.00,352.00l 64.00,0.00 l0.00-96.00 l 32.00,0.00 L 160.00,448.00 c0.00,17.60-14.40,32.00-32.00,32.00L 64.00,480.00 C 46.40,480.00, 32.00,465.60, 32.00,448.00l0.00-192.00 l 32.00,0.00 L 64.00,352.00 z M 64.00,448.00l 64.00,0.00 l0.00-64.00 L 64.00,384.00 L 64.00,448.00 z M 480.00,448.00L 480.00,480.00 l-96.00,0.00 + c-17.601,0.00-32.00-14.40-32.00-32.00l0.00-160.00 c0.00-17.60, 14.399-32.00, 32.00-32.00l 96.00,0.00 l0.00,32.00 l-96.00,0.00 L 384.00,448.00 L 480.00,448.00 z M 320.00,400.00L 320.00,448.00 c0.00,17.60-14.40,32.00-32.00,32.00l-96.00,0.00 l0.00-224.00 l 96.00,0.00 + c 17.60,0.00, 32.00,14.40, 32.00,32.00l0.00,48.00 c0.00,17.60-4.40,32.00-22.00,32.00C 315.60,368.00, 320.00,382.40, 320.00,400.00z M 288.00,288.00l-64.00,0.00 l0.00,64.00 l 64.00,0.00 L 288.00,288.00 z M 288.00,384.00l-64.00,0.00 L 224.00,448.00 l 64.00,0.00 L 288.00,384.00 zM 416.00,192.00 L 208.00-32.00 L 96.00,112.00 L 137.00,147.00 L 208.00,73.00 L 384.00,224.00 Z" /> +<glyph unicode="" d="M 512.00,480.00 L 512.00,288.00 L 442.87,357.13 L 336.87,251.13 L 283.13,304.87 L 389.13,410.87 L 320.00,480.00 ZM 122.87,410.87 L 228.87,304.87 L 175.13,251.13 L 69.13,357.13 L 0.00,288.00 L 0.00,480.00 L 192.00,480.00 ZM 442.87,90.87 L 512.00,160.00 L 512.00-32.00 L 320.00-32.00 L 389.13,37.13 L 283.13,143.13 L 336.87,196.87 ZM 228.87,143.13 L 122.87,37.13 L 192.00-32.00 L 0.00-32.00 L 0.00,160.00 L 69.13,90.87 L 175.13,196.87 Z" /> +<glyph unicode="" d="M 128.00,448.00L 384.00,448.00L 384.00,384.00L 128.00,384.00zM 480.00,352.00L 32.00,352.00 C 14.40,352.00,0.00,337.60,0.00,320.00l0.00-160.00 c0.00-17.60, 14.398-32.00, 32.00-32.00l 96.00,0.00 l0.00-128.00 l 256.00,0.00 L 384.00,128.00 l 96.00,0.00 c 17.60,0.00, 32.00,14.40, 32.00,32.00L 512.00,320.00 + C 512.00,337.60, 497.60,352.00, 480.00,352.00z M 352.00,32.00L 160.00,32.00 L 160.00,192.00 l 192.00,0.00 L 352.00,32.00 z M 487.20,304.00c0.00-12.813-10.387-23.20-23.199-23.20 + c-12.813,0.00-23.201,10.387-23.201,23.20s 10.388,23.20, 23.201,23.20C 476.814,327.20, 487.20,316.813, 487.20,304.00z" /> +<glyph unicode="" d="M 256.00,480.00C 114.615,480.00,0.00,365.386,0.00,224.00c0.00-141.385, 114.614-256.00, 256.00-256.00c 141.385,0.00, 256.00,114.615, 256.00,256.00 + C 512.00,365.386, 397.385,480.00, 256.00,480.00z M 256.00,8.00c-119.293,0.00-216.00,96.706-216.00,216.00c0.00,119.293, 96.707,216.00, 216.00,216.00c 119.295,0.00, 216.00-96.707, 216.00-216.00 + C 472.00,104.706, 375.295,8.00, 256.00,8.00z M 192.00,320.00c0.00-17.673-14.327-32.00-32.00-32.00s-32.00,14.327-32.00,32.00s 14.327,32.00, 32.00,32.00S 192.00,337.673, 192.00,320.00z + M 384.00,320.00c0.00-17.673-14.326-32.00-32.00-32.00s-32.00,14.327-32.00,32.00s 14.326,32.00, 32.00,32.00S 384.00,337.673, 384.00,320.00zM 256.00,154.00 C 326.537,154.00 387.344,182.766 415.231,215.596 C 404.795,129.986 337.087,64.00 256.00,64.00 C 174.941,64.00 107.251,130.013 96.778,215.584 C 124.671,182.761 185.471,154.00 256.00,154.00 Z" /> +<glyph unicode="" d="M 352.00,32.00 L 480.00,32.00 L 512.00,96.00 L 512.00-32.00 L 320.00-32.00 L 320.00,75.107 C 385.556,103.349 432.00,173.688 432.00,256.00 C 432.00,363.216 353.201,447.133 256.00,447.133 C 158.797,447.133 80.00,363.217 80.00,256.00 C 80.00,173.688 126.443,103.349 192.00,75.107 L 192.00-32.00 L 0.00-32.00 L 0.00,96.00 L 32.00,32.00 L 160.00,32.00 L 160.00,48.295 C 66.185,81.525 0.00,161.996 0.00,256.00 C 0.00,379.712 114.615,480.00 256.00,480.00 C 397.385,480.00 512.00,379.712 512.00,256.00 C 512.00,161.996 445.815,81.525 352.00,48.295 L 352.00,32.00 Z" /> +<glyph unicode="" d="M 384.00,377.00 L 384.00,352.00 L 448.00,352.00 L 448.00,320.00 L 352.00,320.00 L 352.00,393.00 L 416.00,423.00 L 416.00,448.00 L 352.00,448.00 L 352.00,480.00 L 448.00,480.00 L 448.00,407.00 ZM 338.00,352.00L 270.00,352.00L 176.00,258.00L 82.00,352.00L 14.00,352.00L 142.00,224.00L 14.00,96.00L 82.00,96.00L 176.00,190.00L 270.00,96.00L 338.00,96.00L 210.00,224.00 z" /> +<glyph unicode="" d="M 384.00,25.00 L 384.00,0.00 L 448.00,0.00 L 448.00-32.00 L 352.00-32.00 L 352.00,41.00 L 416.00,71.00 L 416.00,96.00 L 352.00,96.00 L 352.00,128.00 L 448.00,128.00 L 448.00,55.00 ZM 338.00,352.00L 270.00,352.00L 176.00,258.00L 82.00,352.00L 14.00,352.00L 142.00,224.00L 14.00,96.00L 82.00,96.00L 176.00,190.00L 270.00,96.00L 338.00,96.00L 210.00,224.00 z" /> +<glyph unicode="" d="M0.00,32.00L 288.00,32.00L 288.00-32.00L0.00-32.00zM 96.00,480.00L 448.00,480.00L 448.00,416.00L 96.00,416.00zM 138.694,64.00 L 241.038,456.082 L 302.963,439.918 L 204.838,64.00 ZM 464.887-32.00 L 400.00,32.887 L 335.113-32.00 L 304.00-0.887 L 368.887,64.00 L 304.00,128.887 L 335.113,160.00 L 400.00,95.113 L 464.887,160.00 L 496.00,128.887 L 431.113,64.00 L 496.00-0.887 Z" /> +<glyph unicode="" d="M0.00,256.00L 512.00,256.00L 512.00,192.00L0.00,192.00z" /> +<glyph unicode="" d="M0.00,448.00l0.00-448.00 l 512.00,0.00 L 512.00,448.00 L0.00,448.00 z M 192.00,160.00l0.00,96.00 l 128.00,0.00 l0.00-96.00 L 192.00,160.00 z M 320.00,128.00l0.00-96.00 L 192.00,32.00 l0.00,96.00 L 320.00,128.00 z M 320.00,384.00l0.00-96.00 L 192.00,288.00 L 192.00,384.00 L 320.00,384.00 z M 160.00,384.00l0.00-96.00 L 32.00,288.00 L 32.00,384.00 L 160.00,384.00 z + M 32.00,256.00l 128.00,0.00 l0.00-96.00 L 32.00,160.00 L 32.00,256.00 z M 352.00,256.00l 128.00,0.00 l0.00-96.00 L 352.00,160.00 L 352.00,256.00 z M 352.00,288.00L 352.00,384.00 l 128.00,0.00 l0.00-96.00 L 352.00,288.00 z M 32.00,128.00l 128.00,0.00 l0.00-96.00 L 32.00,32.00 L 32.00,128.00 z M 352.00,32.00l0.00,96.00 l 128.00,0.00 l0.00-96.00 L 352.00,32.00 z" /> +<glyph unicode="" d="M 161.009,64.00l 28.80,96.00l 132.382,0.00 l 28.80-96.00l 56.816,0.00 L 311.809,384.00L 200.191,384.00 l-96.00-320.00L 161.009,64.00 z M 237.809,320.00l 36.382,0.00 l 28.80-96.00l-93.982,0.00 + L 237.809,320.00z" /> +<glyph unicode="" d="M 256.00,320.00C 151.316,320.00, 58.378,269.722,0.00,192.00c 58.378-77.723, 151.316-128.00, 256.00-128.00c 104.684,0.00, 197.622,50.277, 256.00,128.00 + C 453.622,269.722, 360.684,320.00, 256.00,320.00z M 224.00,256.00c 17.673,0.00, 32.00-14.327, 32.00-32.00s-14.327-32.00-32.00-32.00s-32.00,14.327-32.00,32.00S 206.327,256.00, 224.00,256.00z + M 386.808,127.352c-19.824-10.129-40.826-17.931-62.423-23.188C 302.141,98.746, 279.134,96.00, 256.00,96.00 + c-23.133,0.00-46.141,2.746-68.384,8.162c-21.597,5.259-42.599,13.061-62.423,23.188c-31.51,16.101-60.111,38.205-83.82,64.649 + c 23.709,26.444, 52.31,48.55, 83.82,64.649c 16.168,8.261, 33.121,14.973, 50.541,20.02C 165.79,261.547, 160.00,243.451, 160.00,224.00 + c0.00-53.02, 42.981-96.00, 96.00-96.00c 53.019,0.00, 96.00,42.98, 96.00,96.00c0.00,19.451-5.791,37.547-15.733,52.67c 17.419-5.048, 34.372-11.76, 50.541-20.021 + c 31.511-16.099, 60.109-38.204, 83.819-64.649C 446.917,165.557, 418.318,143.45, 386.808,127.352z M 430.459,358.139 + C 376.099,385.916, 317.403,400.00, 256.00,400.00c-61.403,0.00-120.099-14.084-174.459-41.861C 52.155,343.123, 24.675,324.187,0.00,302.101l0.00-54.603 + c 27.669,29.283, 60.347,53.877, 96.097,72.145C 145.907,345.095, 199.706,358.00, 256.00,358.00s 110.093-12.905, 159.902-38.358 + c 35.751-18.268, 68.429-42.862, 96.098-72.145L 512.00,302.10 C 487.325,324.187, 459.846,343.123, 430.459,358.139z" /> +<glyph unicode="" d="M 256.00,384.00C 149.962,384.00, 64.00,298.039, 64.00,192.00s 85.961-192.00, 192.00-192.00c 106.037,0.00, 192.00,85.961, 192.00,192.00S 362.037,384.00, 256.00,384.00z + M 357.822,90.177C 330.626,62.979, 294.464,48.00, 256.00,48.00s-74.625,14.979-101.823,42.177C 126.979,117.374, 112.00,153.536, 112.00,192.00 + s 14.979,74.625, 42.177,101.823C 181.375,321.021, 217.536,336.00, 256.00,336.00s 74.626-14.979, 101.821-42.177 + C 385.022,266.625, 400.00,230.464, 400.00,192.00S 385.021,117.374, 357.822,90.177zM 162.965,378.069l-21.47,42.939C 92.058,396.24, 51.76,355.942, 26.992,306.504l 42.938-21.47 + C 90.054,325.202, 122.796,357.945, 162.965,378.069zM 442.067,285.035l 42.939,21.469C 460.24,355.942, 419.943,396.24, 370.504,421.008l-21.472-42.939 + C 389.201,357.945, 421.944,325.203, 442.067,285.035zM 256.00,288.00l-32.00,0.00 l0.00-96.00 c0.00-5.055, 2.35-9.555, 6.011-12.486l-0.006-0.008l 80.00-64.00l 19.988,24.988L 256.00,199.689L 256.00,288.00 z" /> +<glyph unicode="" d="M 160.00,352.00L 32.00,224.00L 160.00,96.00L 224.00,96.00L 96.00,224.00L 224.00,352.00 zM 352.00,352.00L 288.00,352.00L 416.00,224.00L 288.00,96.00L 352.00,96.00L 480.00,224.00 z" /> +<glyph unicode="" d="M 224.00,128.00L 288.00,128.00L 288.00,64.00L 224.00,64.00zM 352.00,352.00 C 369.673,352.00 384.00,337.673 384.00,320.00 L 384.00,224.00 L 288.00,160.00 L 224.00,160.00 L 224.00,192.00 L 320.00,256.00 L 320.00,288.00 L 160.00,288.00 L 160.00,352.00 L 352.00,352.00 ZM 256.00,432.00 C 200.441,432.00 148.208,410.364 108.922,371.078 C 69.636,331.792 48.00,279.559 48.00,224.00 C 48.00,168.441 69.636,116.208 108.922,76.922 C 148.208,37.636 200.441,16.00 256.00,16.00 C 311.559,16.00 363.792,37.636 403.078,76.922 C 442.364,116.208 464.00,168.441 464.00,224.00 C 464.00,279.559 442.364,331.792 403.078,371.078 C 363.792,410.364 311.559,432.00 256.00,432.00 Z M 256.00,480.00 L 256.00,480.00 C 397.385,480.00 512.00,365.385 512.00,224.00 C 512.00,82.615 397.385-32.00 256.00-32.00 C 114.615-32.00 0.00,82.615 0.00,224.00 C 0.00,365.385 114.615,480.00 256.00,480.00 Z" /> +<glyph unicode="" d="M0.00,416.00l0.00-384.00 l 512.00,0.00 L 512.00,416.00 L0.00,416.00 z M 96.00,64.00L 32.00,64.00 l0.00,64.00 l 64.00,0.00 L 96.00,64.00 z M 96.00,192.00L 32.00,192.00 l0.00,64.00 l 64.00,0.00 L 96.00,192.00 z M 96.00,320.00L 32.00,320.00 L 32.00,384.00 l 64.00,0.00 L 96.00,320.00 z M 384.00,64.00L 128.00,64.00 L 128.00,384.00 l 256.00,0.00 L 384.00,64.00 z + M 480.00,64.00l-64.00,0.00 l0.00,64.00 l 64.00,0.00 L 480.00,64.00 z M 480.00,192.00l-64.00,0.00 l0.00,64.00 l 64.00,0.00 L 480.00,192.00 z M 480.00,320.00l-64.00,0.00 L 416.00,384.00 l 64.00,0.00 L 480.00,320.00 zM 192.00,320.00L 192.00,128.00L 320.00,224.00 z" /> +<glyph unicode="" d="M0.00,416.00l0.00-416.00 l 512.00,0.00 L 512.00,416.00 L0.00,416.00 z M 480.00,32.00L 32.00,32.00 L 32.00,384.00 l 448.00,0.00 L 480.00,32.00 zM 352.00,304.00A48.00,48.00 1620.00 1,0 448.00,304A48.00,48.00 1620.00 1,0 352.00,304zM 448.00,64.00 L 64.00,64.00 L 160.00,320.00 L 288.00,160.00 L 352.00,208.00 Z" /> +<glyph unicode="" d="M 96.00,480.00l0.00-512.00 l 160.00,160.00l 160.00-160.00L 416.00,480.00 L 96.00,480.00 z M 384.00,45.255l-128.00,128.00l-128.00-128.00L 128.00,448.00 l 256.00,0.00 L 384.00,45.255 z" /> +<glyph unicode="" d="M 238.444,142.443c 2.28-4.524, 3.495-9.579, 3.495-14.848c0.00-8.808-3.372-17.029-9.496-23.154l-81.69-81.69 + c-6.124-6.124-14.348-9.496-23.154-9.496s-17.03,3.372-23.154,9.496l-49.69,49.69c-6.124,6.125-9.496,14.348-9.496,23.154 + s 3.372,17.03, 9.496,23.154l 81.69,81.691c 6.124,6.123, 14.348,9.496, 23.154,9.496c 5.269,0.00, 10.322-1.215, 14.848-3.494l 32.669,32.668 + c-13.935,10.705-30.72,16.08-47.517,16.08c-19.993,0.00-39.986-7.583-55.154-22.751l-81.69-81.691 + c-30.335-30.335-30.335-79.975,0.00-110.309l 49.69-49.691c 15.167-15.166, 35.16-22.75, 55.153-22.75 + c 19.994,0.00, 39.987,7.584, 55.154,22.751l 81.69,81.69c 27.91,27.91, 30.119,72.149, 6.672,102.673L 238.444,142.443zM 489.248,407.558l-49.69,49.691C 424.391,472.417, 404.398,480.00, 384.404,480.00c-19.993,0.00-39.985-7.583-55.153-22.751l-81.691-81.691 + c-27.91-27.91-30.119-72.149-6.671-102.671l 32.669,32.67c-2.279,4.525-3.494,9.58-3.494,14.847c0.00,8.808, 3.372,17.03, 9.496,23.154 + l 81.691,81.691c 6.123,6.124, 14.347,9.497, 23.153,9.497c 8.808,0.00, 17.03-3.373, 23.154-9.497l 49.69-49.691 + c 6.124-6.124, 9.496-14.347, 9.496-23.154c0.00-8.807-3.372-17.03-9.496-23.154l-81.69-81.691c-6.124-6.124-14.347-9.496-23.154-9.496 + c-5.268,0.00-10.322,1.215-14.848,3.495l-32.669-32.669c 13.936-10.705, 30.72-16.08, 47.517-16.08c 19.994,0.00, 39.987,7.584, 55.154,22.752 + l 81.69,81.69C 519.584,327.584, 519.584,377.223, 489.248,407.558zM 116.684,340.688L 20.687,436.685L 43.315,459.313L 139.312,363.316zM 192.00,480.00L 224.00,480.00L 224.00,384.00L 192.00,384.00zM0.00,288.00L 96.00,288.00L 96.00,256.00L0.00,256.00zM 395.316,107.312L 491.314,11.314L 468.686-11.314L 372.688,84.684zM 288.00,64.00L 320.00,64.00L 320.00-32.00L 288.00-32.00zM 416.00,192.00L 512.00,192.00L 512.00,160.00L 416.00,160.00z" /> +<glyph unicode="" d="M 160.00,128.00c 8.80-8.80, 23.637-8.363, 32.971,0.971L 351.03,287.029C 360.364,296.363, 360.80,311.20, 352.00,320.00 + s-23.637,8.363-32.971-0.971L 160.971,160.971C 151.637,151.637, 151.20,136.80, 160.00,128.00zM 238.444,142.444c 2.28-4.525, 3.495-9.58, 3.495-14.848c0.00-8.808-3.372-17.03-9.496-23.154l-81.691-81.691 + c-6.124-6.124-14.347-9.496-23.154-9.496s-17.03,3.372-23.154,9.496l-49.691,49.691c-6.124,6.124-9.496,14.347-9.496,23.154 + s 3.372,17.03, 9.496,23.154l 81.691,81.691c 6.124,6.124, 14.347,9.497, 23.154,9.497c 5.268,0.00, 10.322-1.215, 14.848-3.495l 32.669,32.669 + c-13.935,10.705-30.72,16.08-47.517,16.08c-19.993,0.00-39.986-7.583-55.154-22.751l-81.691-81.691 + c-30.335-30.335-30.335-79.974,0.00-110.309l 49.691-49.691C 87.611-24.416, 107.604-32.00, 127.597-32.00 + c 19.994,0.00, 39.987,7.584, 55.154,22.751l 81.691,81.691c 27.91,27.91, 30.119,72.149, 6.672,102.672L 238.444,142.444zM 489.249,407.558l-49.691,49.691C 424.391,472.417, 404.398,480.00, 384.404,480.00c-19.993,0.00-39.986-7.583-55.154-22.751l-81.691-81.691 + c-27.91-27.91-30.119-72.149-6.671-102.671l 32.669,32.67c-2.279,4.525-3.494,9.58-3.494,14.847c0.00,8.808, 3.372,17.03, 9.496,23.154 + l 81.691,81.691c 6.124,6.124, 14.347,9.497, 23.154,9.497s 17.03-3.373, 23.154-9.497l 49.691-49.691 + c 6.124-6.124, 9.496-14.347, 9.496-23.154s-3.372-17.03-9.496-23.154l-81.691-81.691c-6.124-6.124-14.347-9.496-23.154-9.496 + c-5.268,0.00-10.322,1.215-14.848,3.495l-32.669-32.669c 13.936-10.705, 30.72-16.08, 47.517-16.08c 19.994,0.00, 39.987,7.584, 55.154,22.751 + l 81.691,81.691C 519.584,327.584, 519.584,377.223, 489.249,407.558z" /> +<glyph unicode="" d="M 288.00,355.814L 288.00,480.00 l 192.00-192.00L 288.00,96.00L 288.00,222.912 C 64.625,228.153, 74.206,71.016, 131.07-32.00 + C-9.286,119.707, 20.52,362.785, 288.00,355.814z" /> +<glyph unicode="" d="M 380.931-32.00C 437.794,71.016, 447.375,228.153, 224.00,222.912L 224.00,96.00 L 32.00,288.00L 224.00,480.00l0.00-124.186 + C 491.481,362.785, 521.285,119.707, 380.931-32.00z" /> +<glyph unicode="" d="M 112.50,256.00 C 174.356,256.00 224.50,205.855 224.50,144.00 C 224.50,82.144 174.356,32.00 112.50,32.00 C 50.644,32.00 0.50,82.144 0.50,144.00 L 0.00,160.00 C 0.00,283.712 100.288,384.00 224.00,384.00 L 224.00,320.00 C 181.263,320.00 141.083,303.357 110.863,273.137 C 105.046,267.319 99.737,261.129 94.948,254.627 C 100.667,255.527 106.528,256.00 112.50,256.00 ZM 400.50,256.00 C 462.355,256.00 512.50,205.855 512.50,144.00 C 512.50,82.144 462.355,32.00 400.50,32.00 C 338.645,32.00 288.50,82.144 288.50,144.00 L 288.00,160.00 C 288.00,283.712 388.288,384.00 512.00,384.00 L 512.00,320.00 C 469.263,320.00 429.083,303.357 398.863,273.137 C 393.045,267.319 387.736,261.129 382.947,254.627 C 388.667,255.527 394.527,256.00 400.50,256.00 Z" /> +<glyph unicode="" d="M0.00,448.00L 512.00,448.00L 512.00,384.00L0.00,384.00zM 192.00,352.00L 512.00,352.00L 512.00,288.00L 192.00,288.00zM 192.00,256.00L 512.00,256.00L 512.00,192.00L 192.00,192.00zM 192.00,160.00L 512.00,160.00L 512.00,96.00L 192.00,96.00zM0.00,64.00L 512.00,64.00L 512.00,0.00L0.00,0.00zM 128.00,320.00 L 128.00,128.00 L 0.00,224.00 Z" /> +<glyph unicode="" d="M0.00,448.00L 512.00,448.00L 512.00,384.00L0.00,384.00zM 192.00,352.00L 512.00,352.00L 512.00,288.00L 192.00,288.00zM 192.00,256.00L 512.00,256.00L 512.00,192.00L 192.00,192.00zM 192.00,160.00L 512.00,160.00L 512.00,96.00L 192.00,96.00zM0.00,64.00L 512.00,64.00L 512.00,0.00L0.00,0.00zM 0.00,128.00 L 0.00,320.00 L 128.00,224.00 Z" /> +<glyph unicode="" d="M 192.00,64.00L 512.00,64.00L 512.00,0.00L 192.00,0.00zM 192.00,256.00L 512.00,256.00L 512.00,192.00L 192.00,192.00zM 192.00,448.00L 512.00,448.00L 512.00,384.00L 192.00,384.00zM 96.00,480.00 L 96.00,352.00 L 64.00,352.00 L 64.00,448.00 L 32.00,448.00 L 32.00,480.00 ZM 64.00,217.00 L 64.00,192.00 L 128.00,192.00 L 128.00,160.00 L 32.00,160.00 L 32.00,233.00 L 96.00,263.00 L 96.00,288.00 L 32.00,288.00 L 32.00,320.00 L 128.00,320.00 L 128.00,247.00 ZM 128.00,128.00 L 128.00-32.00 L 32.00-32.00 L 32.00,0.00 L 96.00,0.00 L 96.00,32.00 L 32.00,32.00 L 32.00,64.00 L 96.00,64.00 L 96.00,96.00 L 32.00,96.00 L 32.00,128.00 Z" /> +<glyph unicode="" d="M 192.00,448.00l 320.00,0.00 l0.00-64.00 L 192.00,384.00 L 192.00,448.00 z M 192.00,256.00l 320.00,0.00 l0.00-64.00 L 192.00,192.00 L 192.00,256.00 z M 192.00,64.00l 320.00,0.00 l0.00-64.00 L 192.00,0.00 L 192.00,64.00 zM0.00,416.00A64.00,64.00 1620.00 1,0 128.00,416A64.00,64.00 1620.00 1,0 0.00,416zM0.00,224.00A64.00,64.00 1620.00 1,0 128.00,224A64.00,64.00 1620.00 1,0 0.00,224zM0.00,32.00A64.00,64.00 1620.00 1,0 128.00,32A64.00,64.00 1620.00 1,0 0.00,32z" /> +<glyph unicode="" d="M 32.00,480.00L 224.00,480.00L 224.00,448.00L 32.00,448.00zM 288.00,480.00L 480.00,480.00L 480.00,448.00L 288.00,448.00zM 476.00,320.00l-28.00,0.00 L 448.00,448.00 L 320.00,448.00 l0.00-128.00 L 192.00,320.00 L 192.00,448.00 L 64.00,448.00 l0.00-128.00 L 36.00,320.00 c-19.80,0.00-36.00-16.20-36.00-36.00l0.00-280.00 c0.00-19.80, 16.20-36.00, 36.00-36.00l 152.00,0.00 c 19.80,0.00, 36.00,16.20, 36.00,36.00L 224.00,192.00 l 64.00,0.00 + l0.00-188.00 c0.00-19.80, 16.20-36.00, 36.00-36.00l 152.00,0.00 c 19.80,0.00, 36.00,16.20, 36.00,36.00L 512.00,284.00 C 512.00,303.80, 495.80,320.00, 476.00,320.00z M 174.00,0.00L 50.00,0.00 c-9.90,0.00-18.00,7.20-18.00,16.00 + s 8.10,16.00, 18.00,16.00l 124.00,0.00 c 9.90,0.00, 18.00-7.20, 18.00-16.00S 183.90,0.00, 174.00,0.00z M 272.00,224.00l-32.00,0.00 c-8.80,0.00-16.00,7.20-16.00,16.00s 7.20,16.00, 16.00,16.00l 32.00,0.00 c 8.80,0.00, 16.00-7.20, 16.00-16.00 + S 280.80,224.00, 272.00,224.00z M 462.00,0.00L 338.00,0.00 c-9.90,0.00-18.00,7.20-18.00,16.00s 8.10,16.00, 18.00,16.00l 124.00,0.00 c 9.90,0.00, 18.00-7.20, 18.00-16.00S 471.90,0.00, 462.00,0.00z" /> +<glyph unicode="" d="M 416.00,320.00L 416.00,400.00 c0.00,8.80-7.20,16.00-16.00,16.00L 288.00,416.00 L 288.00,448.00 c0.00,17.60-14.40,32.00-32.00,32.00l-64.00,0.00 c-17.602,0.00-32.00-14.40-32.00-32.00l0.00-32.00 L 48.00,416.00 c-8.801,0.00-16.00-7.20-16.00-16.00l0.00-320.00 + c0.00-8.80, 7.199-16.00, 16.00-16.00l 144.00,0.00 l0.00-96.00 l 224.00,0.00 l 96.00,96.00L 512.00,320.00 L 416.00,320.00 z M 192.00,447.943c 0.017,0.019, 0.036,0.039, 0.057,0.057l 63.884,0.00 + c 0.021-0.018, 0.041-0.038, 0.059-0.057L 256.00,416.00 l-64.00,0.00 L 192.00,447.943 z M 96.00,352.00L 96.00,384.00 l 256.00,0.00 l0.00-32.00 L 96.00,352.00 z M 416.00,13.255L 416.00,64.00 l 50.745,0.00 L 416.00,13.255z M 480.00,96.00l-96.00,0.00 l0.00-96.00 + L 224.00,0.00 L 224.00,288.00 l 256.00,0.00 L 480.00,96.00 z" /> +<glyph unicode="" d="M 445.387,125.423c-22.827,22.778-51.864,34.536-78.973,34.536l-14.556,0.00 l-31.952,32.004l 127.81,128.019 + c 31.952,32.005, 31.952,96.014,0.00,128.019L 256.001,255.973L 64.285,448.00c-31.952-32.004-31.952-96.014,0.00-128.019l 127.811-128.017 + l-31.953-32.004l-14.557,0.00 c-27.11,0.00-56.146-11.759-78.974-34.538c-40.811-40.721-46.325-101.242-12.315-135.175 + C 69.282-24.704, 89.441-32.00, 110.795-32.00c 27.108,0.00, 56.145,11.757, 78.973,34.536c 26.792,26.732, 38.371,62.00, 33.542,92.674l 32.692,32.744 + l 32.688-32.744c-4.828-30.674, 6.753-65.941, 33.542-92.674C 345.063-20.243, 374.098-32.00, 401.206-32.00 + c 21.354,0.00, 41.512,7.296, 56.497,22.248C 491.713,24.181, 486.197,84.702, 445.387,125.423z M 176.512,57.231 + c-3.849-8.941-9.505-17.173-16.813-24.463c-7.318-7.302-15.586-12.959-24.574-16.812c-8.066-3.458-16.48-5.284-24.331-5.284 + c-7.573,0.00-18.306,1.701-26.431,9.806c-8.068,8.052-9.76,18.659-9.76,26.144c0.00,7.771, 1.821,16.105, 5.263,24.106 + c 3.85,8.942, 9.507,17.173, 16.813,24.463c 7.317,7.303, 15.586,12.957, 24.575,16.812c 8.067,3.457, 16.48,5.284, 24.332,5.284 + c 7.573,0.00, 18.306-1.70, 26.429-9.807c 8.067-8.049, 9.761-18.658, 9.761-26.142C 181.777,73.567, 179.957,65.23, 176.512,57.231z + M 256.002,146.702c-24.957,0.00-45.188,20.266-45.188,45.263c0.00,24.996, 20.231,45.26, 45.188,45.26s 45.186-20.264, 45.186-45.26 + C 301.188,166.966, 280.958,146.702, 256.002,146.702z M 427.636,20.479c-8.124-8.104-18.856-9.806-26.43-9.806 + c-7.852,0.00-16.265,1.826-24.333,5.284c-8.986,3.853-17.254,9.51-24.571,16.812c-7.307,7.29-12.963,15.521-16.813,24.463 + c-3.443,7.999-5.263,16.336-5.263,24.106c0.00,7.483, 1.692,18.094, 9.76,26.143c 8.123,8.104, 18.856,9.807, 26.43,9.807 + c 7.85,0.00, 16.265-1.827, 24.33-5.284c 8.989-3.854, 17.258-9.509, 24.575-16.812c 7.305-7.29, 12.962-15.521, 16.813-24.463 + c 3.442-7.999, 5.263-16.335, 5.263-24.106C 437.396,39.138, 435.702,28.53, 427.636,20.479z" /> +<glyph unicode="" d="M0.00,448.00L 512.00,448.00L 512.00,384.00L0.00,384.00zM0.00,352.00L 512.00,352.00L 512.00,288.00L0.00,288.00zM0.00,256.00L 512.00,256.00L 512.00,192.00L0.00,192.00zM0.00,160.00L 512.00,160.00L 512.00,96.00L0.00,96.00zM0.00,64.00L 512.00,64.00L 512.00,0.00L0.00,0.00z" /> +<glyph unicode="" d="M0.00,448.00L 512.00,448.00L 512.00,384.00L0.00,384.00zM 192.00,352.00L 512.00,352.00L 512.00,288.00L 192.00,288.00zM 192.00,160.00L 512.00,160.00L 512.00,96.00L 192.00,96.00zM0.00,256.00L 512.00,256.00L 512.00,192.00L0.00,192.00zM0.00,64.00L 512.00,64.00L 512.00,0.00L0.00,0.00z" /> +<glyph unicode="" d="M0.00,448.00L 512.00,448.00L 512.00,384.00L0.00,384.00zM 96.00,352.00L 416.00,352.00L 416.00,288.00L 96.00,288.00zM 96.00,160.00L 416.00,160.00L 416.00,96.00L 96.00,96.00zM0.00,256.00L 512.00,256.00L 512.00,192.00L0.00,192.00zM0.00,64.00L 512.00,64.00L 512.00,0.00L0.00,0.00z" /> +<glyph unicode="" d="M0.00,448.00L 512.00,448.00L 512.00,384.00L0.00,384.00zM0.00,352.00L 320.00,352.00L 320.00,288.00L0.00,288.00zM0.00,160.00L 320.00,160.00L 320.00,96.00L0.00,96.00zM0.00,256.00L 512.00,256.00L 512.00,192.00L0.00,192.00zM0.00,64.00L 512.00,64.00L 512.00,0.00L0.00,0.00z" /> +<glyph unicode="" d="M 512.00,183.771l0.00,80.458 l-79.572,7.957c-4.093,15.021-10.044,29.274-17.605,42.49l 52.298,63.919L 410.595,435.12l-63.918-52.298 + c-13.217,7.562-27.471,13.513-42.491,17.604L 296.229,480.00l-80.458,0.00 l-7.957-79.573c-15.021-4.093-29.274-10.043-42.49-17.604 + L 101.405,435.12L 44.88,378.595l 52.298-63.918c-7.562-13.216-13.513-27.47-17.605-42.49L0.00,264.229l0.00-80.458 l 79.573-7.957 + c 4.093-15.021, 10.043-29.274, 17.605-42.491L 44.88,69.405l 56.524-56.524l 63.919,52.298c 13.216-7.562, 27.47-13.514, 42.49-17.605 + L 215.771-32.00l 80.458,0.00 l 7.957,79.572c 15.021,4.093, 29.274,10.044, 42.491,17.605l 63.918-52.298l 56.524,56.524l-52.298,63.918 + c 7.562,13.217, 13.514,27.471, 17.605,42.49L 512.00,183.771z M 352.00,192.00l-64.00-64.00l-64.00,0.00 l-64.00,64.00l0.00,64.00 l 64.00,64.00l 64.00,0.00 l 64.00-64.00L 352.00,192.00 z" /> +<glyph unicode="" d="M 451.716,380.285l-71.432,71.431C 364.728,467.272, 334.00,480.00, 312.00,480.00L 72.00,480.00 C 50.00,480.00, 32.00,462.00, 32.00,440.00l0.00-432.00 c0.00-22.00, 18.00-40.00, 40.00-40.00l 368.00,0.00 c 22.00,0.00, 40.00,18.00, 40.00,40.00 + L 480.00,312.00 C 480.00,334.00, 467.272,364.729, 451.716,380.285z M 429.089,357.657c 1.565-1.565, 3.125-3.487, 4.64-5.657L 352.00,352.00 L 352.00,433.728 + c 2.17-1.515, 4.092-3.075, 5.657-4.64L 429.089,357.657z M 448.00,8.00c0.00-4.336-3.664-8.00-8.00-8.00L 72.00,0.00 c-4.336,0.00-8.00,3.664-8.00,8.00L 64.00,440.00 c0.00,4.336, 3.664,8.00, 8.00,8.00 + l 240.00,0.00 c 2.416,0.00, 5.127-0.305, 8.00-0.852L 320.00,320.00 l 127.148,0.00 c 0.547-2.873, 0.852-5.583, 0.852-8.00L 448.00,8.00 z" /> +<glyph unicode="" d="M 448.00,480.00L0.00,480.00 l0.00-512.00 l 512.00,0.00 L 512.00,416.00 L 448.00,480.00z M 256.00,416.00l 64.00,0.00 l0.00-128.00 l-64.00,0.00 L 256.00,416.00 z M 448.00,32.00L 64.00,32.00 L 64.00,416.00 l 32.00,0.00 l0.00-160.00 l 288.00,0.00 L 384.00,416.00 l 37.489,0.00 L 448.00,389.491L 448.00,32.00 z" /> +<glyph unicode="" d="M 64.00,208.00L 208.00,64.00L 448.00,304.00L 384.00,368.00L 208.00,192.00L 128.00,272.00 z" /> +<glyph unicode=" " horiz-adv-x="256" /> +<glyph class="hidden" unicode="" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" /> +</font></defs></svg>
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.ttf b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.ttf Binary files differnew file mode 100644 index 00000000..4529badb --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.ttf diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.woff b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.woff Binary files differnew file mode 100644 index 00000000..33eea8ea --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/icomoon.woff diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/fonts/readme.md b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/readme.md new file mode 100644 index 00000000..fa5d6394 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/fonts/readme.md @@ -0,0 +1 @@ +Icons are generated and provided by the http://icomoon.io service. diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/img/anchor.gif b/extlib/tinymce/js/tinymce/skins/lightgray/img/anchor.gif Binary files differnew file mode 100644 index 00000000..606348c7 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/img/anchor.gif diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/img/loader.gif b/extlib/tinymce/js/tinymce/skins/lightgray/img/loader.gif Binary files differnew file mode 100644 index 00000000..c69e9372 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/img/loader.gif diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/img/object.gif b/extlib/tinymce/js/tinymce/skins/lightgray/img/object.gif Binary files differnew file mode 100644 index 00000000..cccd7f02 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/img/object.gif diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/img/trans.gif b/extlib/tinymce/js/tinymce/skins/lightgray/img/trans.gif Binary files differnew file mode 100644 index 00000000..38848651 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/img/trans.gif diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/img/wline.gif b/extlib/tinymce/js/tinymce/skins/lightgray/img/wline.gif Binary files differnew file mode 100644 index 00000000..7d0a4dbc --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/img/wline.gif diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/skin.ie7.min.css b/extlib/tinymce/js/tinymce/skins/lightgray/skin.ie7.min.css new file mode 100644 index 00000000..1d13b877 --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/skin.ie7.min.css @@ -0,0 +1 @@ +.mce-container,.mce-container *,.mce-widget,.mce-widget *{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#000;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-container ::-webkit-scrollbar{width:8px;height:8px;-webkit-border-radius:4px}.mce-container ::-webkit-scrollbar-track,.mce-container ::-webkit-scrollbar-track-piece{background-color:transparent}.mce-container ::-webkit-scrollbar-thumb{background-color:rgba(53,57,71,0.3);width:6px;height:6px;-webkit-border-radius:4px}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.mce-tinymce{visibility:visible!important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;background:#FFF;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block;border-radius:2px}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}.mce-edit-area{background:#FFF;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid #c5c5c5;width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#d9d9d9}.mce-grid td div{border:1px solid #808080;width:12px;height:12px;margin:2px;cursor:pointer}.mce-grid td div:hover{border-color:black}.mce-grid td div:focus{border-color:#59a5e1;outline:1px solid rgba(82,168,236,0.8);border-color:rgba(82,168,236,0.8)}.mce-grid{border-spacing:2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover{border-color:#c5c5c5}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#e8e8e8;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#c4daff;background:#deeafa}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#AAA;opacity:.6;filter:alpha(opacity=60);zoom:1;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scroll{position:relative}.mce-panel{border:0 solid #9e9e9e;background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fdfdfd,#ddd);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdfdfd),to(#ddd));background-image:-webkit-linear-gradient(top,#fdfdfd,#ddd);background-image:-o-linear-gradient(top,#fdfdfd,#ddd);background-image:linear-gradient(to bottom,#fdfdfd,#ddd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffdfdfd',endColorstr='#ffdddddd',GradientType=0);zoom:1}.mce-floatpanel{position:absolute;-webkit-box-shadow:#ccc 5px 5px 5px;-moz-box-shadow:#ccc 5px 5px 5px;box-shadow:#ccc 5px 5px 5px}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{top:0;left:0;background:#fff;-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;background:#FFF;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#FFF;position:fixed;top:0;left:0;opacity:0;-webkit-transition:opacity 150ms ease-in;transition:opacity 150ms ease-in}.mce-window.mce-in{opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #EEE;position:relative}.mce-window-head .mce-close{position:absolute;right:15px;top:9px;font-size:20px;font-weight:bold;line-height:20px;color:#CCC;text-shadow:0 1px 0 white;cursor:pointer;height:20px;overflow:hidden}.mce-close:hover{color:#AAA}.mce-window-head .mce-title{display:inline-block;*display:inline;*zoom:1;line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:10px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:whiteSmoke;border-top:1px solid #DDD;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window.mce-fullscreen,.mce-window.mce-fullscreen .mce-foot{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:#fff;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-inner{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-tooltip-inner{-webkit-box-shadow:0 0 5px #000;-moz-box-shadow:0 0 5px #000;box-shadow:0 0 5px #000}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-n .mce-tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:0;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-btn{border:1px solid #c5c5c5;position:relative;color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fff,#d9d9d9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#d9d9d9));background-image:-webkit-linear-gradient(top,#fff,#d9d9d9);background-image:-o-linear-gradient(top,#fff,#d9d9d9);background-image:linear-gradient(to bottom,#fff,#d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffd9d9d9',GradientType=0);zoom:1;border-color:#d9d9d9 #d9d9d9 #b3b3b3;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.mce-btn:hover,.mce-btn:focus{text-decoration:none;color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#e3e3e3;background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#ccc));background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(to bottom,#f2f2f2,#ccc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffcccccc',GradientType=0);zoom:1;border-color:#ccc #ccc #a6a6a6;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-btn.mce-disabled,.mce-btn.mce-disabled:hover{cursor:default;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.65;filter:alpha(opacity=65);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#d6d6d6;background-image:-moz-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:-webkit-gradient(linear,0 0,0 100%,from(#e6e6e6),to(#bfbfbf));background-image:-webkit-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:-o-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:linear-gradient(to bottom,#e6e6e6,#bfbfbf);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6',endColorstr='#ffbfbfbf',GradientType=0);zoom:1;border-color:#bfbfbf #bfbfbf #999;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.mce-btn button{padding:4px 10px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px #fff}.mce-primary{min-width:50px;color:#fff;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);zoom:1;border-color:#04c #04c #002b80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-primary:hover,.mce-primary:focus{color:#fff;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#005fb3;background-image:-moz-linear-gradient(top,#0077b3,#003cb3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#0077b3),to(#003cb3));background-image:-webkit-linear-gradient(top,#0077b3,#003cb3);background-image:-o-linear-gradient(top,#0077b3,#003cb3);background-image:linear-gradient(to bottom,#0077b3,#003cb3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0077b3',endColorstr='#ff003cb3',GradientType=0);zoom:1;border-color:#003cb3 #003cb3 #026;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-primary button{color:#fff}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:3px 5px;font-size:12px;line-height:15px}.mce-btn-small i{margin-top:0}.mce-btn .mce-caret{margin-top:8px;*margin-top:6px;margin-left:0}.mce-btn-small .mce-caret{margin-top:6px;*margin-top:4px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #444;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#999}.mce-caret.mce-up{border-bottom:4px solid #444;border-top:0}.mce-btn-group .mce-btn{border-width:1px 0 1px 0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-btn-group .mce-btn:hover,.mce-btn-group .mce-btn:focus{color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#e3e3e3;background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#ccc));background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(to bottom,#f2f2f2,#ccc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffcccccc',GradientType=0);zoom:1;border-color:#ccc #ccc #a6a6a6;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-btn-group .mce-btn.mce-disabled,.mce-btn-group .mce-btn.mce-disabled:hover{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fff,#d9d9d9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#d9d9d9));background-image:-webkit-linear-gradient(top,#fff,#d9d9d9);background-image:-o-linear-gradient(top,#fff,#d9d9d9);background-image:linear-gradient(to bottom,#fff,#d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffd9d9d9',GradientType=0);zoom:1;border-color:#d9d9d9 #d9d9d9 #b3b3b3;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-btn-group .mce-btn.mce-active,.mce-btn-group .mce-btn.mce-active:hover,.mce-btn-group .mce-btn:active{color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#d6d6d6;background-image:-moz-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:-webkit-gradient(linear,0 0,0 100%,from(#e6e6e6),to(#bfbfbf));background-image:-webkit-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:-o-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:linear-gradient(to bottom,#e6e6e6,#bfbfbf);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6',endColorstr='#ffbfbfbf',GradientType=0);zoom:1;border-color:#bfbfbf #bfbfbf #999;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.mce-btn-group .mce-btn.mce-disabled button{opacity:.65;filter:alpha(opacity=65);zoom:1}.mce-btn-group .mce-first{border-left:1px solid #c5c5c5;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.mce-btn-group .mce-last{border-right:1px solid #c5c5c5;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.mce-btn-group .mce-first.mce-last{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fdfdfd,#ddd);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdfdfd),to(#ddd));background-image:-webkit-linear-gradient(top,#fdfdfd,#ddd);background-image:-o-linear-gradient(top,#fdfdfd,#ddd);background-image:linear-gradient(to bottom,#fdfdfd,#ddd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffdfdfd',endColorstr='#ffdddddd',GradientType=0);zoom:1;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0}.mce-checked i.mce-i-checkbox{color:#000;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox{border:1px solid #59a5e1;border:1px solid rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}.mce-colorbutton .mce-ico{position:relative}.mce-colorpicker{background:#FFF}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:4px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-14px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-17px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;border-left:1px solid transparent;border-right:1px solid transparent}.mce-colorbutton:hover .mce-open{border-left-color:#c5c5c5;border-right-color:#c5c5c5}.mce-combobox{display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;width:100px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.mce-combobox input{border-color:1px solid #c5c5c5;border-right-color:rgba(0,0,0,0.15);height:28px}.mce-combobox.mce-has-open input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.mce-combobox .mce-btn{border-left:0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox *:focus{border-color:#59a5e1;border-color:rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#000}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:gray;color:white}.mce-path .mce-divider{display:inline}.mce-fieldset{border:0 solid #9e9e9e;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-iframe{border:0 solid #c5c5c5;width:100%;height:100%}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);border:0 solid #c5c5c5;overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label-disabled .mce-text{color:#999}.mce-label.mce-multiline{white-space:pre-wrap}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:none}.mce-menubar{border:1px solid #ddd}.mce-menubar .mce-menubtn button{color:#000}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:transparent;background:#ddd;filter:none}.mce-menubtn.mce-disabled span{color:#999}.mce-menubtn span{margin-right:2px;line-height:20px;*line-height:16px}.mce-menubtn.mce-btn-small span{font-size:12px;line-height:15px;*line-height:16px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item.mce-disabled .mce-text{color:#999}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:#fff;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0);zoom:1}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text{color:#fff}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:white}.mce-menu-item.mce-disabled:hover{background:#CCC}.mce-menu-shortcut{display:inline-block;color:#999}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #666}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret{border-left-color:#FFF}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item-sep,.mce-menu-item-sep:hover{padding:0;height:1px;margin:9px 1px;overflow:hidden;background:#e5e5e5;border-bottom:1px solid white;cursor:default;filter:none}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item.mce-active{background-color:#c8def4;outline:1px solid #c5c5c5}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa;background-color:transparent;outline:0}.mce-menu-item-checkbox.mce-active{background-color:#FFF;outline:0}.mce-menu{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:2px 0 0;min-width:160px;background:#FFF;border:1px solid #CCC;border:1px solid rgba(0,0,0,0.2);z-index:1002;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline;*zoom:1}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}i.mce-radio{padding:1px;margin:0 3px 0 0;background-color:#fafafa;border:1px solid #cacece;-webkit-border-radius:8px;-moz-border-radius:8px;border-radius:8px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fdfdfd,#ddd);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdfdfd),to(#ddd));background-image:-webkit-linear-gradient(top,#fdfdfd,#ddd);background-image:-o-linear-gradient(top,#fdfdfd,#ddd);background-image:linear-gradient(to bottom,#fdfdfd,#ddd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffdfdfd',endColorstr='#ffdddddd',GradientType=0);zoom:1}i.mce-radio:after{font-family:Arial;font-size:12px;color:#000;content:'\25cf'}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#000}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent;border-right:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#c5c5c5;border-right-color:#c5c5c5}.mce-splitbtn button{padding-right:4px}.mce-splitbtn .mce-open{padding-left:4px}.mce-splitbtn .mce-open.mce-active{-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #ccc}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #ccc;border-width:1px 1px 0 0;background:#e3e3e3;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#fdfdfd}.mce-tab.mce-active{background:#fdfdfd;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-textbox{background:#FFF;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);display:inline-block;-webkit-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#000}.mce-textbox:focus{border-color:rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}@font-face{font-family:'icomoon';src:url('fonts/icomoon.eot');src:url('fonts/icomoon.eot?#iefix') format('embedded-opentype'),url('fonts/icomoon.svg#icomoon') format('svg'),url('fonts/icomoon.woff') format('woff'),url('fonts/icomoon.ttf') format('truetype');font-weight:normal;font-style:normal}@font-face{font-family:'icomoon-small';src:url('fonts/icomoon-small.eot');src:url('fonts/icomoon-small.eot?#iefix') format('embedded-opentype'),url('fonts/icomoon-small.svg#icomoon') format('svg'),url('fonts/icomoon-small.woff') format('woff'),url('fonts/icomoon-small.ttf') format('truetype');font-weight:normal;font-style:normal}.mce-ico{font-family:'icomoon';font-style:normal;font-weight:normal;font-size:16px;line-height:16px;vertical-align:text-top;-webkit-font-smoothing:antialiased;display:inline-block;background:transparent center center;width:16px;height:16px;color:#333;-ie7-icon:' '}.mce-btn-small .mce-ico{font-family:'icomoon-small'}.mce-ico,i.mce-i-checkbox{zoom:expression(this.runtimeStyle['zoom'] = '1',this.innerHTML = this.currentStyle['-ie7-icon'].substr(1,1)+' ')}.mce-i-save{-ie7-icon:"\e000"}.mce-i-newdocument{-ie7-icon:"\e001"}.mce-i-fullpage{-ie7-icon:"\e002"}.mce-i-alignleft{-ie7-icon:"\e003"}.mce-i-aligncenter{-ie7-icon:"\e004"}.mce-i-alignright{-ie7-icon:"\e005"}.mce-i-alignjustify{-ie7-icon:"\e006"}.mce-i-cut{-ie7-icon:"\e007"}.mce-i-paste{-ie7-icon:"\e008"}.mce-i-searchreplace{-ie7-icon:"\e009"}.mce-i-bullist{-ie7-icon:"\e00a"}.mce-i-numlist{-ie7-icon:"\e00b"}.mce-i-indent{-ie7-icon:"\e00c"}.mce-i-outdent{-ie7-icon:"\e00d"}.mce-i-blockquote{-ie7-icon:"\e00e"}.mce-i-undo{-ie7-icon:"\e00f"}.mce-i-redo{-ie7-icon:"\e010"}.mce-i-link{-ie7-icon:"\e011"}.mce-i-unlink{-ie7-icon:"\e012"}.mce-i-anchor{-ie7-icon:"\e013"}.mce-i-image{-ie7-icon:"\e014"}.mce-i-media{-ie7-icon:"\e015"}.mce-i-help{-ie7-icon:"\e016"}.mce-i-code{-ie7-icon:"\e017"}.mce-i-inserttime{-ie7-icon:"\e018"}.mce-i-preview{-ie7-icon:"\e019"}.mce-i-forecolor{-ie7-icon:"\e01a"}.mce-i-backcolor{-ie7-icon:"\e01a"}.mce-i-table{-ie7-icon:"\e01b"}.mce-i-hr{-ie7-icon:"\e01c"}.mce-i-removeformat{-ie7-icon:"\e01d"}.mce-i-subscript{-ie7-icon:"\e01e"}.mce-i-superscript{-ie7-icon:"\e01f"}.mce-i-charmap{-ie7-icon:"\e020"}.mce-i-emoticons{-ie7-icon:"\e021"}.mce-i-print{-ie7-icon:"\e022"}.mce-i-fullscreen{-ie7-icon:"\e023"}.mce-i-spellchecker{-ie7-icon:"\e024"}.mce-i-nonbreaking{-ie7-icon:"\e025"}.mce-i-template{-ie7-icon:"\e026"}.mce-i-pagebreak{-ie7-icon:"\e027"}.mce-i-restoredraft{-ie7-icon:"\e028"}.mce-i-untitled{-ie7-icon:"\e029"}.mce-i-bold{-ie7-icon:"\e02a"}.mce-i-italic{-ie7-icon:"\e02b"}.mce-i-underline{-ie7-icon:"\e02c"}.mce-i-strikethrough{-ie7-icon:"\e02d"}.mce-i-visualchars{-ie7-icon:"\e02e"}.mce-i-ltr{-ie7-icon:"\e02f"}.mce-i-rtl{-ie7-icon:"\e030"}.mce-i-copy{-ie7-icon:"\e031"}.mce-i-resize{-ie7-icon:"\e032"}.mce-i-browse{-ie7-icon:"\e034"}.mce-i-checkbox,.mce-i-selected{-ie7-icon:"\e033"}.mce-i-selected{visibility:hidden}.mce-i-backcolor{background:#BBB}
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/skins/lightgray/skin.min.css b/extlib/tinymce/js/tinymce/skins/lightgray/skin.min.css new file mode 100644 index 00000000..74b56bed --- /dev/null +++ b/extlib/tinymce/js/tinymce/skins/lightgray/skin.min.css @@ -0,0 +1 @@ +.mce-container,.mce-container *,.mce-widget,.mce-widget *{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#000;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-container ::-webkit-scrollbar{width:8px;height:8px;-webkit-border-radius:4px}.mce-container ::-webkit-scrollbar-track,.mce-container ::-webkit-scrollbar-track-piece{background-color:transparent}.mce-container ::-webkit-scrollbar-thumb{background-color:rgba(53,57,71,0.3);width:6px;height:6px;-webkit-border-radius:4px}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.mce-tinymce{visibility:visible!important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;background:#FFF;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block;border-radius:2px}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}.mce-edit-area{background:#FFF;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid #c5c5c5;width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#d9d9d9}.mce-grid td div{border:1px solid #808080;width:12px;height:12px;margin:2px;cursor:pointer}.mce-grid td div:hover{border-color:black}.mce-grid td div:focus{border-color:#59a5e1;outline:1px solid rgba(82,168,236,0.8);border-color:rgba(82,168,236,0.8)}.mce-grid{border-spacing:2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover{border-color:#c5c5c5}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#e8e8e8;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#c4daff;background:#deeafa}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#AAA;opacity:.6;filter:alpha(opacity=60);zoom:1;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.mce-scroll{position:relative}.mce-panel{border:0 solid #9e9e9e;background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fdfdfd,#ddd);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdfdfd),to(#ddd));background-image:-webkit-linear-gradient(top,#fdfdfd,#ddd);background-image:-o-linear-gradient(top,#fdfdfd,#ddd);background-image:linear-gradient(to bottom,#fdfdfd,#ddd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffdfdfd',endColorstr='#ffdddddd',GradientType=0);zoom:1}.mce-floatpanel{position:absolute;-webkit-box-shadow:#ccc 5px 5px 5px;-moz-box-shadow:#ccc 5px 5px 5px;box-shadow:#ccc 5px 5px 5px}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{top:0;left:0;background:#fff;-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;background:#FFF;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#FFF;position:fixed;top:0;left:0;opacity:0;-webkit-transition:opacity 150ms ease-in;transition:opacity 150ms ease-in}.mce-window.mce-in{opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #EEE;position:relative}.mce-window-head .mce-close{position:absolute;right:15px;top:9px;font-size:20px;font-weight:bold;line-height:20px;color:#CCC;text-shadow:0 1px 0 white;cursor:pointer;height:20px;overflow:hidden}.mce-close:hover{color:#AAA}.mce-window-head .mce-title{display:inline-block;*display:inline;*zoom:1;line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:10px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:whiteSmoke;border-top:1px solid #DDD;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window.mce-fullscreen,.mce-window.mce-fullscreen .mce-foot{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:#fff;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-inner{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-tooltip-inner{-webkit-box-shadow:0 0 5px #000;-moz-box-shadow:0 0 5px #000;box-shadow:0 0 5px #000}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-n .mce-tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:0;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:0;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-btn{border:1px solid #c5c5c5;position:relative;color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fff,#d9d9d9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#d9d9d9));background-image:-webkit-linear-gradient(top,#fff,#d9d9d9);background-image:-o-linear-gradient(top,#fff,#d9d9d9);background-image:linear-gradient(to bottom,#fff,#d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffd9d9d9',GradientType=0);zoom:1;border-color:#d9d9d9 #d9d9d9 #b3b3b3;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.mce-btn:hover,.mce-btn:focus{text-decoration:none;color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#e3e3e3;background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#ccc));background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(to bottom,#f2f2f2,#ccc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffcccccc',GradientType=0);zoom:1;border-color:#ccc #ccc #a6a6a6;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-btn.mce-disabled,.mce-btn.mce-disabled:hover{cursor:default;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:.65;filter:alpha(opacity=65);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#d6d6d6;background-image:-moz-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:-webkit-gradient(linear,0 0,0 100%,from(#e6e6e6),to(#bfbfbf));background-image:-webkit-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:-o-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:linear-gradient(to bottom,#e6e6e6,#bfbfbf);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6',endColorstr='#ffbfbfbf',GradientType=0);zoom:1;border-color:#bfbfbf #bfbfbf #999;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.mce-btn button{padding:4px 10px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px #fff}.mce-primary{min-width:50px;color:#fff;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);zoom:1;border-color:#04c #04c #002b80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-primary:hover,.mce-primary:focus{color:#fff;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#005fb3;background-image:-moz-linear-gradient(top,#0077b3,#003cb3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#0077b3),to(#003cb3));background-image:-webkit-linear-gradient(top,#0077b3,#003cb3);background-image:-o-linear-gradient(top,#0077b3,#003cb3);background-image:linear-gradient(to bottom,#0077b3,#003cb3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0077b3',endColorstr='#ff003cb3',GradientType=0);zoom:1;border-color:#003cb3 #003cb3 #026;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-primary button{color:#fff}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:3px 5px;font-size:12px;line-height:15px}.mce-btn-small i{margin-top:0}.mce-btn .mce-caret{margin-top:8px;*margin-top:6px;margin-left:0}.mce-btn-small .mce-caret{margin-top:6px;*margin-top:4px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #444;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#999}.mce-caret.mce-up{border-bottom:4px solid #444;border-top:0}.mce-btn-group .mce-btn{border-width:1px 0 1px 0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.mce-btn-group .mce-btn:hover,.mce-btn-group .mce-btn:focus{color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#e3e3e3;background-image:-moz-linear-gradient(top,#f2f2f2,#ccc);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#ccc));background-image:-webkit-linear-gradient(top,#f2f2f2,#ccc);background-image:-o-linear-gradient(top,#f2f2f2,#ccc);background-image:linear-gradient(to bottom,#f2f2f2,#ccc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffcccccc',GradientType=0);zoom:1;border-color:#ccc #ccc #a6a6a6;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-btn-group .mce-btn.mce-disabled,.mce-btn-group .mce-btn.mce-disabled:hover{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fff,#d9d9d9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#d9d9d9));background-image:-webkit-linear-gradient(top,#fff,#d9d9d9);background-image:-o-linear-gradient(top,#fff,#d9d9d9);background-image:linear-gradient(to bottom,#fff,#d9d9d9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffd9d9d9',GradientType=0);zoom:1;border-color:#d9d9d9 #d9d9d9 #b3b3b3;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25)}.mce-btn-group .mce-btn.mce-active,.mce-btn-group .mce-btn.mce-active:hover,.mce-btn-group .mce-btn:active{color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#d6d6d6;background-image:-moz-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:-webkit-gradient(linear,0 0,0 100%,from(#e6e6e6),to(#bfbfbf));background-image:-webkit-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:-o-linear-gradient(top,#e6e6e6,#bfbfbf);background-image:linear-gradient(to bottom,#e6e6e6,#bfbfbf);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6',endColorstr='#ffbfbfbf',GradientType=0);zoom:1;border-color:#bfbfbf #bfbfbf #999;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.mce-btn-group .mce-btn.mce-disabled button{opacity:.65;filter:alpha(opacity=65);zoom:1}.mce-btn-group .mce-first{border-left:1px solid #c5c5c5;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.mce-btn-group .mce-last{border-right:1px solid #c5c5c5;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.mce-btn-group .mce-first.mce-last{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fdfdfd,#ddd);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdfdfd),to(#ddd));background-image:-webkit-linear-gradient(top,#fdfdfd,#ddd);background-image:-o-linear-gradient(top,#fdfdfd,#ddd);background-image:linear-gradient(to bottom,#fdfdfd,#ddd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffdfdfd',endColorstr='#ffdddddd',GradientType=0);zoom:1;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0}.mce-checked i.mce-i-checkbox{color:#000;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox{border:1px solid #59a5e1;border:1px solid rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}.mce-colorbutton .mce-ico{position:relative}.mce-colorpicker{background:#FFF}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:4px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-14px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-17px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;border-left:1px solid transparent;border-right:1px solid transparent}.mce-colorbutton:hover .mce-open{border-left-color:#c5c5c5;border-right-color:#c5c5c5}.mce-combobox{display:inline-block;*display:inline;*zoom:1;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;width:100px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.mce-combobox input{border-color:1px solid #c5c5c5;border-right-color:rgba(0,0,0,0.15);height:28px}.mce-combobox.mce-has-open input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.mce-combobox .mce-btn{border-left:0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox *:focus{border-color:#59a5e1;border-color:rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#000}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:gray;color:white}.mce-path .mce-divider{display:inline}.mce-fieldset{border:0 solid #9e9e9e;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-iframe{border:0 solid #c5c5c5;width:100%;height:100%}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);border:0 solid #c5c5c5;overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label-disabled .mce-text{color:#999}.mce-label.mce-multiline{white-space:pre-wrap}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:none}.mce-menubar{border:1px solid #ddd}.mce-menubar .mce-menubtn button{color:#000}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:transparent;background:#ddd;filter:none}.mce-menubtn.mce-disabled span{color:#999}.mce-menubtn span{margin-right:2px;line-height:20px;*line-height:16px}.mce-menubtn.mce-btn-small span{font-size:12px;line-height:15px;*line-height:16px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item.mce-disabled .mce-text{color:#999}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:#fff;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0);zoom:1}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text{color:#fff}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:white}.mce-menu-item.mce-disabled:hover{background:#CCC}.mce-menu-shortcut{display:inline-block;color:#999}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #666}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret{border-left-color:#FFF}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item-sep,.mce-menu-item-sep:hover{padding:0;height:1px;margin:9px 1px;overflow:hidden;background:#e5e5e5;border-bottom:1px solid white;cursor:default;filter:none}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item.mce-active{background-color:#c8def4;outline:1px solid #c5c5c5}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa;background-color:transparent;outline:0}.mce-menu-item-checkbox.mce-active{background-color:#FFF;outline:0}.mce-menu{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:2px 0 0;min-width:160px;background:#FFF;border:1px solid #CCC;border:1px solid rgba(0,0,0,0.2);z-index:1002;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline;*zoom:1}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}i.mce-radio{padding:1px;margin:0 3px 0 0;background-color:#fafafa;border:1px solid #cacece;-webkit-border-radius:8px;-moz-border-radius:8px;border-radius:8px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#fdfdfd,#ddd);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdfdfd),to(#ddd));background-image:-webkit-linear-gradient(top,#fdfdfd,#ddd);background-image:-o-linear-gradient(top,#fdfdfd,#ddd);background-image:linear-gradient(to bottom,#fdfdfd,#ddd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffdfdfd',endColorstr='#ffdddddd',GradientType=0);zoom:1}i.mce-radio:after{font-family:Arial;font-size:12px;color:#000;content:'\25cf'}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#000}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent;border-right:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#c5c5c5;border-right-color:#c5c5c5}.mce-splitbtn button{padding-right:4px}.mce-splitbtn .mce-open{padding-left:4px}.mce-splitbtn .mce-open.mce-active{-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #ccc}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #ccc;border-width:1px 1px 0 0;background:#e3e3e3;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#fdfdfd}.mce-tab.mce-active{background:#fdfdfd;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-textbox{background:#FFF;border:1px solid #c5c5c5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);display:inline-block;-webkit-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#000}.mce-textbox:focus{border-color:rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}@font-face{font-family:'tinymce';src:url('fonts/icomoon.eot');src:url('fonts/icomoon.eot?#iefix') format('embedded-opentype'),url('fonts/icomoon.svg#icomoon') format('svg'),url('fonts/icomoon.woff') format('woff'),url('fonts/icomoon.ttf') format('truetype');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/icomoon-small.eot');src:url('fonts/icomoon-small.eot?#iefix') format('embedded-opentype'),url('fonts/icomoon-small.svg#icomoon') format('svg'),url('fonts/icomoon-small.woff') format('woff'),url('fonts/icomoon-small.ttf') format('truetype');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce',Arial;font-style:normal;font-weight:normal;font-size:16px;line-height:16px;vertical-align:text-top;-webkit-font-smoothing:antialiased;display:inline-block;background:transparent center center;width:16px;height:16px;color:#333}.mce-btn-small .mce-ico{font-family:'tinymce-small',Arial}.mce-i-save:before{content:"\e000"}.mce-i-newdocument:before{content:"\e001"}.mce-i-fullpage:before{content:"\e002"}.mce-i-alignleft:before{content:"\e003"}.mce-i-aligncenter:before{content:"\e004"}.mce-i-alignright:before{content:"\e005"}.mce-i-alignjustify:before{content:"\e006"}.mce-i-cut:before{content:"\e007"}.mce-i-paste:before{content:"\e008"}.mce-i-searchreplace:before{content:"\e009"}.mce-i-bullist:before{content:"\e00a"}.mce-i-numlist:before{content:"\e00b"}.mce-i-indent:before{content:"\e00c"}.mce-i-outdent:before{content:"\e00d"}.mce-i-blockquote:before{content:"\e00e"}.mce-i-undo:before{content:"\e00f"}.mce-i-redo:before{content:"\e010"}.mce-i-link:before{content:"\e011"}.mce-i-unlink:before{content:"\e012"}.mce-i-anchor:before{content:"\e013"}.mce-i-image:before{content:"\e014"}.mce-i-media:before{content:"\e015"}.mce-i-help:before{content:"\e016"}.mce-i-code:before{content:"\e017"}.mce-i-inserttime:before{content:"\e018"}.mce-i-preview:before{content:"\e019"}.mce-i-forecolor:before{content:"\e01a"}.mce-i-backcolor:before{content:"\e01a"}.mce-i-table:before{content:"\e01b"}.mce-i-hr:before{content:"\e01c"}.mce-i-removeformat:before{content:"\e01d"}.mce-i-subscript:before{content:"\e01e"}.mce-i-superscript:before{content:"\e01f"}.mce-i-charmap:before{content:"\e020"}.mce-i-emoticons:before{content:"\e021"}.mce-i-print:before{content:"\e022"}.mce-i-fullscreen:before{content:"\e023"}.mce-i-spellchecker:before{content:"\e024"}.mce-i-nonbreaking:before{content:"\e025"}.mce-i-template:before{content:"\e026"}.mce-i-pagebreak:before{content:"\e027"}.mce-i-restoredraft:before{content:"\e028"}.mce-i-untitled:before{content:"\e029"}.mce-i-bold:before{content:"\e02a"}.mce-i-italic:before{content:"\e02b"}.mce-i-underline:before{content:"\e02c"}.mce-i-strikethrough:before{content:"\e02d"}.mce-i-visualchars:before{content:"\e02e"}.mce-i-visualblocks:before{content:"\e02e"}.mce-i-ltr:before{content:"\e02f"}.mce-i-rtl:before{content:"\e030"}.mce-i-copy:before{content:"\e031"}.mce-i-resize:before{content:"\e032"}.mce-i-browse:before{content:"\e034"}.mce-i-checkbox:before,.mce-i-selected:before{content:"\e033"}.mce-i-selected{visibility:hidden}i.mce-i-backcolor{text-shadow:none;background:#BBB}
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/themes/modern/theme.min.js b/extlib/tinymce/js/tinymce/themes/modern/theme.min.js new file mode 100644 index 00000000..55e8942e --- /dev/null +++ b/extlib/tinymce/js/tinymce/themes/modern/theme.min.js @@ -0,0 +1 @@ +tinymce.ThemeManager.add("modern",function(e){function t(){function t(t){var i,r=[];if(t)return m(t.split(/[ ,]/),function(t){function n(){var n=e.selection;"bullist"==a&&n.selectorChanged("ul > li",function(e,n){for(var i,r=n.parents.length;r--&&(i=n.parents[r].nodeName,"OL"!=i&&"UL"!=i););t.active("UL"==i)}),"numlist"==a&&n.selectorChanged("ol > li",function(e,n){for(var i,r=n.parents.length;r--&&(i=n.parents[r].nodeName,"OL"!=i&&"UL"!=i););t.active("OL"==i)}),t.settings.stateSelector&&n.selectorChanged(t.settings.stateSelector,function(e){t.active(e)},!0),t.settings.disabledStateSelector&&n.selectorChanged(t.settings.disabledStateSelector,function(e){t.disabled(e)})}var a;"|"==t?i=null:u.has(t)?(t={type:t},c.toolbar_items_size&&(t.size=c.toolbar_items_size),r.push(t),i=null):(i||(i={type:"buttongroup",items:[]},r.push(i)),e.buttons[t]&&(a=t,t=e.buttons[a],t.type=t.type||"button",c.toolbar_items_size&&(t.size=c.toolbar_items_size),t=u.create(t),i.items.push(t),e.initialized?n():e.on("init",n)))}),n.push({type:"toolbar",layout:"flow",items:r}),!0}for(var n=[],i=1;10>i&&t(c["toolbar"+i]);i++);return n.length||t(c.toolbar||h),n}function n(){function t(t){var n;return"|"==t?{text:"|"}:n=e.menuItems[t]}function n(n){var i,r,a,o,s;if(s=tinymce.makeMap((c.removed_menuitems||"").split(/[ ,]/)),c.menu?(r=c.menu[n],o=!0):r=f[n],r){i={text:r.title},a=[],m((r.items||"").split(/[ ,]/),function(e){var n=t(e);n&&!s[e]&&a.push(t(e))}),o||m(e.menuItems,function(e){e.context==n&&("before"==e.separator&&a.push({text:"|"}),e.prependToContext?a.unshift(e):a.push(e),"after"==e.separator&&a.push({text:"|"}))});for(var l=0;l<a.length;l++)"|"==a[l].text&&(0===l||l==a.length-1)&&a.splice(l,1);if(i.menu=a,!i.menu.length)return null}return i}var i,r=[],a=[];if(c.menu)for(i in c.menu)a.push(i);else for(i in f)a.push(i);for(var o=c.menubar?c.menubar.split(/[ ,]/):a,s=0;s<o.length;s++){var l=o[s];l=n(l),l&&r.push(l)}return r}function i(t){function n(e){var n=t.find(e)[0];n&&n.focus()}e.shortcuts.add("Alt+F9","",function(){n("menubar")}),e.shortcuts.add("Alt+F10","",function(){n("toolbar")}),e.shortcuts.add("Alt+F11","",function(){n("elementpath")}),t.on("cancel",function(){e.focus()})}function r(t,n){function i(e){return{width:e.clientWidth,height:e.clientHeight}}var r,a,o,s;r=e.getContainer(),a=e.getContentAreaContainer().firstChild,o=i(r),s=i(a),t=Math.max(c.min_width||100,t),n=Math.max(c.min_height||100,n),t=Math.min(c.max_width||65535,t),n=Math.min(c.max_height||65535,n),d.css(r,"width",t+(o.width-s.width)),d.css(a,"width",t),d.css(a,"height",n),e.fire("ResizeEditor")}function a(t,n){var i=e.getContentAreaContainer();l.resizeTo(i.clientWidth+t,i.clientHeight+n)}function o(){function r(){m&&m.moveRel&&m.visible()&&!m._fixed&&m.moveRel(e.getBody(),["tl-bl","bl-tl"])}function a(){m&&(m.show(),r(),d.addClass(e.getBody(),"mce-edit-focus"))}function o(){m&&(m.hide(),d.removeClass(e.getBody(),"mce-edit-focus"))}function s(){return m?(m.visible()||a(),void 0):(m=l.panel=u.create({type:f?"panel":"floatpanel",classes:"tinymce tinymce-inline",layout:"flex",direction:"column",autohide:!1,autofix:!0,fixed:!!f,border:1,items:[c.menubar===!1?null:{type:"menubar",border:"0 0 1 0",items:n()},c.toolbar===!1?null:{type:"panel",name:"toolbar",layout:"stack",items:t()}]}),m.renderTo(f||document.body).reflow(),i(m),a(),e.on("nodeChange",r),e.on("activate",a),e.on("deactivate",o),void 0)}var m,f;return c.fixed_toolbar_container&&(f=d.select(c.fixed_toolbar_container)[0]),c.content_editable=!0,e.on("focus",s),e.on("blur",o),e.on("remove",function(){m&&(m.remove(),m=null)}),{}}function s(a){var o,s,m;return o=l.panel=u.create({type:"panel",classes:"tinymce",style:"visibility: hidden",layout:"stack",border:1,items:[c.menubar===!1?null:{type:"menubar",border:"0 0 1 0",items:n()},c.toolbar===!1?null:{type:"panel",layout:"stack",items:t()},{type:"panel",name:"iframe",layout:"stack",classes:"edit-area",html:"",border:"1 0 0 0"}]}),c.resize!==!1&&(s={type:"resizehandle",direction:c.resize,onResizeStart:function(){var t=e.getContentAreaContainer().firstChild;m={width:t.clientWidth,height:t.clientHeight}},onResize:function(e){r(m.width+e.deltaX,m.height+e.deltaY)}}),c.statusbar!==!1&&o.add({type:"panel",name:"statusbar",classes:"statusbar",layout:"flow",border:"1 0 0 0",items:[{type:"elementpath"},s]}),o.renderBefore(a.targetNode).reflow(),c.width&&tinymce.DOM.setStyle(o.getEl(),"width",c.width),e.on("remove",function(){o.remove(),o=null}),i(o),{iframeContainer:o.find("#iframe")[0].getEl(),editorContainer:o.getEl()}}var l=this,c=e.settings,u=tinymce.ui.Factory,m=tinymce.each,d=tinymce.DOM,f={file:{title:"File",items:"newdocument"},edit:{title:"Edit",items:"undo redo | cut copy paste pastetext | selectall"},insert:{title:"Insert",items:"|"},view:{title:"View",items:"visualaid |"},format:{title:"Format",items:"bold italic underline strikethrough superscript subscript | formats | removeformat"},table:{title:"Table"},tools:{title:"Tools"}},h="undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image";l.renderUI=function(t){var n=c.skin!==!1?c.skin||"lightgray":!1;return n&&(tinymce.Env.documentMode<=7?tinymce.DOM.loadCSS(tinymce.baseURL+"/skins/"+n+"/skin.ie7.min.css"):tinymce.DOM.loadCSS(tinymce.baseURL+"/skins/"+n+"/skin.min.css"),e.contentCSS.push(tinymce.baseURL+"/skins/"+n+"/content"+(e.inline?".inline":"")+".min.css")),e.on("ProgressState",function(e){l.throbber=l.throbber||new tinymce.ui.Throbber(l.panel.getEl("body")),e.state?l.throbber.show(e.time):l.throbber.hide()}),c.inline?o(t):s(t)},l.resizeTo=r,l.resizeBy=a});
\ No newline at end of file diff --git a/extlib/tinymce/js/tinymce/tinymce.min.js b/extlib/tinymce/js/tinymce/tinymce.min.js new file mode 100644 index 00000000..156c7b69 --- /dev/null +++ b/extlib/tinymce/js/tinymce/tinymce.min.js @@ -0,0 +1,10 @@ +// 4.0.2 (2013-07-18) +!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i<e.length;++i){if(n=s[e[i]]||o(e[i]),!n)throw"module definition dependecy not found: "+e[i];r.push(n)}t.apply(null,r)}function r(e,r,i){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(r===t)throw"invalid module definition, dependencies must be specified";if(i===t)throw"invalid module definition, definition function must be specified";n(r,function(){s[e]=i.apply(null,arguments)})}function i(e){return!!s[e]}function o(t){for(var n=e,r=t.split(/[.\/]/),i=0;i<r.length;++i){if(!n[r[i]])return;n=n[r[i]]}return n}function a(n){for(var r=0;r<n.length;r++){for(var i=e,o=n[r],a=o.split(/[.\/]/),l=0;l<a.length-1;++l)i[a[l]]===t&&(i[a[l]]={}),i=i[a[l]];i[a[a.length-1]]=s[o]}}var s={},l="tinymce/dom/EventUtils",c="tinymce/dom/Sizzle",u="tinymce/dom/DomQuery",d="tinymce/html/Styles",f="tinymce/dom/TreeWalker",p="tinymce/util/Tools",h="tinymce/dom/Range",m="tinymce/html/Entities",g="tinymce/Env",v="tinymce/dom/DOMUtils",y="tinymce/dom/ScriptLoader",b="tinymce/AddOnManager",C="tinymce/html/Node",x="tinymce/html/Schema",w="tinymce/html/SaxParser",_="tinymce/html/DomParser",N="tinymce/html/Writer",E="tinymce/html/Serializer",S="tinymce/dom/Serializer",k="tinymce/dom/TridentSelection",T="tinymce/util/VK",R="tinymce/dom/ControlSelection",A="tinymce/dom/Selection",B="tinymce/dom/RangeUtils",L="tinymce/Formatter",M="tinymce/UndoManager",D="tinymce/EnterKey",H="tinymce/ForceBlocks",P="tinymce/EditorCommands",O="tinymce/util/URI",I="tinymce/util/Class",F="tinymce/ui/Selector",W="tinymce/ui/Collection",z="tinymce/ui/DomUtils",V="tinymce/ui/Control",U="tinymce/ui/Factory",q="tinymce/ui/Container",$="tinymce/ui/DragHelper",j="tinymce/ui/Scrollable",K="tinymce/ui/Panel",G="tinymce/ui/Movable",Y="tinymce/ui/Resizable",X="tinymce/ui/FloatPanel",J="tinymce/ui/KeyboardNavigation",Q="tinymce/ui/Window",Z="tinymce/ui/MessageBox",et="tinymce/WindowManager",tt="tinymce/util/Quirks",nt="tinymce/util/Observable",rt="tinymce/Shortcuts",it="tinymce/Editor",ot="tinymce/util/I18n",at="tinymce/FocusManager",st="tinymce/EditorManager",lt="tinymce/LegacyInput",ct="tinymce/util/XHR",ut="tinymce/util/JSON",dt="tinymce/util/JSONRequest",ft="tinymce/util/JSONP",pt="tinymce/util/LocalStorage",ht="tinymce/Compat",mt="tinymce/ui/Layout",gt="tinymce/ui/AbsoluteLayout",vt="tinymce/ui/Tooltip",yt="tinymce/ui/Widget",bt="tinymce/ui/Button",Ct="tinymce/ui/ButtonGroup",xt="tinymce/ui/Checkbox",wt="tinymce/ui/PanelButton",_t="tinymce/ui/ColorButton",Nt="tinymce/ui/ComboBox",Et="tinymce/ui/Path",St="tinymce/ui/ElementPath",kt="tinymce/ui/FormItem",Tt="tinymce/ui/Form",Rt="tinymce/ui/FieldSet",At="tinymce/ui/FilePicker",Bt="tinymce/ui/FitLayout",Lt="tinymce/ui/FlexLayout",Mt="tinymce/ui/FlowLayout",Dt="tinymce/ui/FormatControls",Ht="tinymce/ui/GridLayout",Pt="tinymce/ui/Iframe",Ot="tinymce/ui/Label",It="tinymce/ui/Toolbar",Ft="tinymce/ui/MenuBar",Wt="tinymce/ui/MenuButton",zt="tinymce/ui/ListBox",Vt="tinymce/ui/MenuItem",Ut="tinymce/ui/Menu",qt="tinymce/ui/Radio",$t="tinymce/ui/ResizeHandle",jt="tinymce/ui/Spacer",Kt="tinymce/ui/SplitButton",Gt="tinymce/ui/StackLayout",Yt="tinymce/ui/TabPanel",Xt="tinymce/ui/TextBox",Jt="tinymce/ui/Throbber";r(l,[],function(){function e(e,t,n,r){e.addEventListener?e.addEventListener(t,n,r||!1):e.attachEvent&&e.attachEvent("on"+t,n)}function t(e,t,n,r){e.removeEventListener?e.removeEventListener(t,n,r||!1):e.detachEvent&&e.detachEvent("on"+t,n)}function n(e,t){function n(){return!1}function r(){return!0}var i,o=t||{},s;for(i in e)"layerX"!==i&&"layerY"!==i&&(o[i]=e[i]);if(o.target||(o.target=o.srcElement||document),e&&a.test(e.type)&&e.pageX===s&&e.clientX!==s){var l=o.target.ownerDocument||document,c=l.documentElement,u=l.body;o.pageX=e.clientX+(c&&c.scrollLeft||u&&u.scrollLeft||0)-(c&&c.clientLeft||u&&u.clientLeft||0),o.pageY=e.clientY+(c&&c.scrollTop||u&&u.scrollTop||0)-(c&&c.clientTop||u&&u.clientTop||0)}return o.preventDefault=function(){o.isDefaultPrevented=r,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},o.stopPropagation=function(){o.isPropagationStopped=r,e&&(e.stopPropagation?e.stopPropagation():e.cancelBubble=!0)},o.stopImmediatePropagation=function(){o.isImmediatePropagationStopped=r,o.stopPropagation()},o.isDefaultPrevented||(o.isDefaultPrevented=n,o.isPropagationStopped=n,o.isImmediatePropagationStopped=n),o}function r(n,r,i){function o(){i.domLoaded||(i.domLoaded=!0,r(c))}function a(){"complete"===l.readyState&&(t(l,"readystatechange",a),o())}function s(){try{l.documentElement.doScroll("left")}catch(e){return setTimeout(s,0),void 0}o()}var l=n.document,c={type:"ready"};return i.domLoaded?(r(c),void 0):(l.addEventListener?e(n,"DOMContentLoaded",o):(e(l,"readystatechange",a),l.documentElement.doScroll&&n===n.top&&s()),e(n,"load",o),void 0)}function i(){function i(e,t){var n,r,i,o;if(n=s[t][e.type])for(r=0,i=n.length;i>r;r++)if(o=n[r],o&&o.func.call(o.scope,e)===!1&&e.preventDefault(),e.isImmediatePropagationStopped())return}var a=this,s={},l,c,u,d,f;c=o+(+new Date).toString(32),d="onmouseenter"in document.documentElement,u="onfocusin"in document.documentElement,f={mouseenter:"mouseover",mouseleave:"mouseout"},l=1,a.domLoaded=!1,a.events=s,a.bind=function(t,o,p,h){function m(e){i(n(e||_.event),g)}var g,v,y,b,C,x,w,_=window;if(t&&3!==t.nodeType&&8!==t.nodeType){for(t[c]?g=t[c]:(g=l++,t[c]=g,s[g]={}),h=h||t,o=o.split(" "),y=o.length;y--;)b=o[y],x=m,C=w=!1,"DOMContentLoaded"===b&&(b="ready"),a.domLoaded&&"ready"===b&&"complete"==t.readyState?p.call(h,n({type:b})):(d||(C=f[b],C&&(x=function(e){var t,r;if(t=e.currentTarget,r=e.relatedTarget,r&&t.contains)r=t.contains(r);else for(;r&&r!==t;)r=r.parentNode;r||(e=n(e||_.event),e.type="mouseout"===e.type?"mouseleave":"mouseenter",e.target=t,i(e,g))})),u||"focusin"!==b&&"focusout"!==b||(w=!0,C="focusin"===b?"focus":"blur",x=function(e){e=n(e||_.event),e.type="focus"===e.type?"focusin":"focusout",i(e,g)}),v=s[g][b],v?"ready"===b&&a.domLoaded?p({type:b}):v.push({func:p,scope:h}):(s[g][b]=v=[{func:p,scope:h}],v.fakeName=C,v.capture=w,v.nativeHandler=x,"ready"===b?r(t,x,a):e(t,C||b,x,w)));return t=v=0,p}},a.unbind=function(e,n,r){var i,o,l,u,d,f;if(!e||3===e.nodeType||8===e.nodeType)return a;if(i=e[c]){if(f=s[i],n){for(n=n.split(" "),l=n.length;l--;)if(d=n[l],o=f[d]){if(r)for(u=o.length;u--;)o[u].func===r&&o.splice(u,1);r&&0!==o.length||(delete f[d],t(e,o.fakeName||d,o.nativeHandler,o.capture))}}else{for(d in f)o=f[d],t(e,o.fakeName||d,o.nativeHandler,o.capture);f={}}for(d in f)return a;delete s[i];try{delete e[c]}catch(p){e[c]=null}}return a},a.fire=function(e,t,r){var o;if(!e||3===e.nodeType||8===e.nodeType)return a;r=n(null,r),r.type=t,r.target=e;do o=e[c],o&&i(r,o),e=e.parentNode||e.ownerDocument||e.defaultView||e.parentWindow;while(e&&!r.isPropagationStopped());return a},a.clean=function(e){var t,n,r=a.unbind;if(!e||3===e.nodeType||8===e.nodeType)return a;if(e[c]&&r(e),e.getElementsByTagName||(e=e.document),e&&e.getElementsByTagName)for(r(e),n=e.getElementsByTagName("*"),t=n.length;t--;)e=n[t],e[c]&&r(e);return a},a.destroy=function(){s={}},a.cancel=function(e){return e&&(e.preventDefault(),e.stopImmediatePropagation()),!1}}var o="mce-data-",a=/^(?:mouse|contextmenu)|click/;return i.Event=new i,i.Event.bind(window,"ready",function(){}),i}),r(c,[],function(){function e(e){return gt.test(e+"")}function n(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>N.cacheLength&&delete e[t.shift()],e[n]=r,r}}function i(e){return e[F]=!0,e}function o(e){var t=L.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t=null}}function a(e,t,n,r){var i,o,a,s,l,c,u,p,h,m;if((t?t.ownerDocument||t:W)!==L&&B(t),t=t||L,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(D&&!r){if(i=vt.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&I(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return et.apply(n,t.getElementsByTagName(e)),n;if((a=i[3])&&z.getElementsByClassName&&t.getElementsByClassName)return et.apply(n,t.getElementsByClassName(a)),n}if(z.qsa&&!H.test(e)){if(u=!0,p=F,h=t,m=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){for(c=d(e),(u=t.getAttribute("id"))?p=u.replace(Ct,"\\$&"):t.setAttribute("id",p),p="[id='"+p+"'] ",l=c.length;l--;)c[l]=p+f(c[l]);h=mt.test(e)&&t.parentNode||t,m=c.join(",")}if(m)try{return et.apply(n,h.querySelectorAll(m)),n}catch(g){}finally{u||t.removeAttribute("id")}}}return C(e.replace(ct,"$1"),t,n,r)}function s(e,t){var n=t&&e,r=n&&(~t.sourceIndex||X)-(~e.sourceIndex||X);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function l(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function c(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function u(e){return i(function(t){return t=+t,i(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function d(e,t){var n,r,i,o,s,l,c,u=$[e+" "];if(u)return t?0:u.slice(0);for(s=e,l=[],c=N.preFilter;s;){(!n||(r=ut.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=dt.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(ct," ")}),s=s.slice(n.length));for(o in N.filter)!(r=ht[o].exec(s))||c[o]&&!(r=c[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?a.error(e):$(e,l).slice(0)}function f(e){for(var t=0,n=e.length,r="";n>t;t++)r+=e[t].value;return r}function p(e,t,n){var r=t.dir,i=n&&"parentNode"===r,o=U++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,l,c,u=V+" "+o;if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i)if(c=t[F]||(t[F]={}),(l=c[r])&&l[0]===u){if((s=l[1])===!0||s===_)return s===!0}else if(l=c[r]=[u],l[1]=e(t,n,a)||_,l[1]===!0)return!0}}function h(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function m(e,t,n,r,i){for(var o,a=[],s=0,l=e.length,c=null!=t;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),c&&t.push(s));return a}function g(e,t,n,r,o,a){return r&&!r[F]&&(r=g(r)),o&&!o[F]&&(o=g(o,a)),i(function(i,a,s,l){var c,u,d,f=[],p=[],h=a.length,g=i||b(t||"*",s.nodeType?[s]:s,[]),v=!e||!i&&t?g:m(g,f,e,s,l),y=n?o||(i?e:h||r)?[]:a:v;if(n&&n(v,y,s,l),r)for(c=m(y,p),r(c,[],s,l),u=c.length;u--;)(d=c[u])&&(y[p[u]]=!(v[p[u]]=d));if(i){if(o||e){if(o){for(c=[],u=y.length;u--;)(d=y[u])&&c.push(v[u]=d);o(null,y=[],c,l)}for(u=y.length;u--;)(d=y[u])&&(c=o?nt.call(i,d):f[u])>-1&&(i[c]=!(a[c]=d))}}else y=m(y===a?y.splice(h,y.length):y),o?o(null,a,y,l):et.apply(a,y)})}function v(e){for(var t,n,r,i=e.length,o=N.relative[e[0].type],a=o||N.relative[" "],s=o?1:0,l=p(function(e){return e===t},a,!0),c=p(function(e){return nt.call(t,e)>-1},a,!0),u=[function(e,n,r){return!o&&(r||n!==T)||((t=n).nodeType?l(e,n,r):c(e,n,r))}];i>s;s++)if(n=N.relative[e[s].type])u=[p(h(u),n)];else{if(n=N.filter[e[s].type].apply(null,e[s].matches),n[F]){for(r=++s;i>r&&!N.relative[e[r].type];r++);return g(s>1&&h(u),s>1&&f(e.slice(0,s-1)).replace(ct,"$1"),n,r>s&&v(e.slice(s,r)),i>r&&v(e=e.slice(r)),i>r&&f(e))}u.push(n)}return h(u)}function y(e,t){var n=0,r=t.length>0,o=e.length>0,s=function(i,s,l,c,u){var d,f,p,h=[],g=0,v="0",y=i&&[],b=null!=u,C=T,x=i||o&&N.find.TAG("*",u&&s.parentNode||s),w=V+=null==C?1:Math.random()||.1;for(b&&(T=s!==L&&s,_=n);null!=(d=x[v]);v++){if(o&&d){for(f=0;p=e[f++];)if(p(d,s,l)){c.push(d);break}b&&(V=w,_=++n)}r&&((d=!p&&d)&&g--,i&&y.push(d))}if(g+=v,r&&v!==g){for(f=0;p=t[f++];)p(y,h,s,l);if(i){if(g>0)for(;v--;)y[v]||h[v]||(h[v]=Q.call(c));h=m(h)}et.apply(c,h),b&&!i&&h.length>0&&g+t.length>1&&a.uniqueSort(c)}return b&&(V=w,T=C),y};return r?i(s):s}function b(e,t,n){for(var r=0,i=t.length;i>r;r++)a(e,t[r],n);return n}function C(e,t,n,r){var i,o,a,s,l,c=d(e);if(!r&&1===c.length){if(o=c[0]=c[0].slice(0),o.length>2&&"ID"===(a=o[0]).type&&9===t.nodeType&&D&&N.relative[o[1].type]){if(t=(N.find.ID(a.matches[0].replace(wt,_t),t)||[])[0],!t)return n;e=e.slice(o.shift().value.length)}for(i=ht.needsContext.test(e)?0:o.length;i--&&(a=o[i],!N.relative[s=a.type]);)if((l=N.find[s])&&(r=l(a.matches[0].replace(wt,_t),mt.test(o[0].type)&&t.parentNode||t))){if(o.splice(i,1),e=r.length&&f(o),!e)return et.apply(n,r),n;break}}return k(e,c)(r,t,!D,n,mt.test(e)),n}function x(){}var w,_,N,E,S,k,T,R,A,B,L,M,D,H,P,O,I,F="sizzle"+-new Date,W=window.document,z={},V=0,U=0,q=n(),$=n(),j=n(),K=!1,G=function(){return 0},Y=typeof t,X=1<<31,J=[],Q=J.pop,Z=J.push,et=J.push,tt=J.slice,nt=J.indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(this[t]===e)return t;return-1},rt="[\\x20\\t\\r\\n\\f]",it="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",ot=it.replace("w","w#"),at="([*^$|!~]?=)",st="\\["+rt+"*("+it+")"+rt+"*(?:"+at+rt+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+ot+")|)|)"+rt+"*\\]",lt=":("+it+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+st.replace(3,8)+")*)|.*)\\)|)",ct=new RegExp("^"+rt+"+|((?:^|[^\\\\])(?:\\\\.)*)"+rt+"+$","g"),ut=new RegExp("^"+rt+"*,"+rt+"*"),dt=new RegExp("^"+rt+"*([\\x20\\t\\r\\n\\f>+~])"+rt+"*"),ft=new RegExp(lt),pt=new RegExp("^"+ot+"$"),ht={ID:new RegExp("^#("+it+")"),CLASS:new RegExp("^\\.("+it+")"),NAME:new RegExp("^\\[name=['\"]?("+it+")['\"]?\\]"),TAG:new RegExp("^("+it.replace("w","w*")+")"),ATTR:new RegExp("^"+st),PSEUDO:new RegExp("^"+lt),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+rt+"*(even|odd|(([+-]|)(\\d*)n|)"+rt+"*(?:([+-]|)"+rt+"*(\\d+)|))"+rt+"*\\)|)","i"),needsContext:new RegExp("^"+rt+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+rt+"*((?:-\\d)?\\d*)"+rt+"*\\)|)(?=[^-]|$)","i")},mt=/[\x20\t\r\n\f]*[+~]/,gt=/^[^{]+\{\s*\[native code/,vt=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,yt=/^(?:input|select|textarea|button)$/i,bt=/^h\d$/i,Ct=/'|\\/g,xt=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,wt=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,_t=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{et.apply(J=tt.call(W.childNodes),W.childNodes),J[W.childNodes.length].nodeType}catch(Nt){et={apply:J.length?function(e,t){Z.apply(e,tt.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}S=a.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},B=a.setDocument=function(n){var r=n?n.ownerDocument||n:W;return r!==L&&9===r.nodeType&&r.documentElement?(L=r,M=r.documentElement,D=!S(r),z.getElementsByTagName=o(function(e){return e.appendChild(r.createComment("")),!e.getElementsByTagName("*").length}),z.attributes=o(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),z.getElementsByClassName=o(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),z.getByName=o(function(e){e.id=F+0,e.appendChild(L.createElement("a")).setAttribute("name",F),e.appendChild(L.createElement("i")).setAttribute("name",F),M.appendChild(e);var t=r.getElementsByName&&r.getElementsByName(F).length===2+r.getElementsByName(F+0).length;return M.removeChild(e),t}),z.sortDetached=o(function(e){return e.compareDocumentPosition&&1&e.compareDocumentPosition(L.createElement("div"))}),N.attrHandle=o(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==Y&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},z.getByName?(N.find.ID=function(e,t){if(typeof t.getElementById!==Y&&D){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},N.filter.ID=function(e){var t=e.replace(wt,_t);return function(e){return e.getAttribute("id")===t}}):(N.find.ID=function(e,n){if(typeof n.getElementById!==Y&&D){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==Y&&r.getAttributeNode("id").value===e?[r]:t:[]}},N.filter.ID=function(e){var t=e.replace(wt,_t);return function(e){var n=typeof e.getAttributeNode!==Y&&e.getAttributeNode("id");return n&&n.value===t}}),N.find.TAG=z.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==Y?t.getElementsByTagName(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},N.find.NAME=z.getByName&&function(e,t){return typeof t.getElementsByName!==Y?t.getElementsByName(name):void 0},N.find.CLASS=z.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==Y&&D?t.getElementsByClassName(e):void 0},P=[],H=[":focus"],(z.qsa=e(r.querySelectorAll))&&(o(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||H.push("\\["+rt+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||H.push(":checked")}),o(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&H.push("[*^$]="+rt+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||H.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),H.push(",.*:")})),(z.matchesSelector=e(O=M.matchesSelector||M.mozMatchesSelector||M.webkitMatchesSelector||M.oMatchesSelector||M.msMatchesSelector))&&o(function(e){z.disconnectedMatch=O.call(e,"div"),O.call(e,"[s!='']:x"),P.push("!=",lt)}),H=new RegExp(H.join("|")),P=P.length&&new RegExp(P.join("|")),I=e(M.contains)||M.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},G=M.compareDocumentPosition?function(e,t){if(e===t)return K=!0,0;var n=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return n?1&n||R&&t.compareDocumentPosition(e)===n?e===r||I(W,e)?-1:t===r||I(W,t)?1:A?nt.call(A,e)-nt.call(A,t):0:4&n?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var n,i=0,o=e.parentNode,a=t.parentNode,l=[e],c=[t];if(e===t)return K=!0,0;if(!o||!a)return e===r?-1:t===r?1:o?-1:a?1:0;if(o===a)return s(e,t);for(n=e;n=n.parentNode;)l.unshift(n);for(n=t;n=n.parentNode;)c.unshift(n);for(;l[i]===c[i];)i++;return i?s(l[i],c[i]):l[i]===W?-1:c[i]===W?1:0},L):L},a.matches=function(e,t){return a(e,null,null,t)},a.matchesSelector=function(e,t){if((e.ownerDocument||e)!==L&&B(e),t=t.replace(xt,"='$1']"),z.matchesSelector&&D&&(!P||!P.test(t))&&!H.test(t))try{var n=O.call(e,t);if(n||z.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return a(t,L,null,[e]).length>0},a.contains=function(e,t){return(e.ownerDocument||e)!==L&&B(e),I(e,t)},a.attr=function(e,t){var n;return(e.ownerDocument||e)!==L&&B(e),D&&(t=t.toLowerCase()),(n=N.attrHandle[t])?n(e):!D||z.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},a.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},a.uniqueSort=function(e){var t,n=[],r=0,i=0;if(K=!z.detectDuplicates,R=!z.sortDetached,A=!z.sortStable&&e.slice(0),e.sort(G),K){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return e},E=a.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=E(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=E(t);return n},N=a.selectors={cacheLength:50,createPseudo:i,match:ht,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(wt,_t),e[3]=(e[4]||e[5]||"").replace(wt,_t),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||a.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&a.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return ht.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&ft.test(n)&&(t=d(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(wt,_t).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=q[e+" "];return t||(t=new RegExp("(^|"+rt+")"+e+"("+rt+"|$)"))&&q(e,function(e){return t.test(e.className||typeof e.getAttribute!==Y&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=a.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var c,u,d,f,p,h,m=o!==a?"nextSibling":"previousSibling",g=t.parentNode,v=s&&t.nodeName.toLowerCase(),y=!l&&!s;if(g){if(o){for(;m;){for(d=t;d=d[m];)if(s?d.nodeName.toLowerCase()===v:1===d.nodeType)return!1;h=m="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?g.firstChild:g.lastChild],a&&y){for(u=g[F]||(g[F]={}),c=u[e]||[],p=c[0]===V&&c[1],f=c[0]===V&&c[2],d=p&&g.childNodes[p];d=++p&&d&&d[m]||(f=p=0)||h.pop();)if(1===d.nodeType&&++f&&d===t){u[e]=[V,p,f];break}}else if(y&&(c=(t[F]||(t[F]={}))[e])&&c[0]===V)f=c[1];else for(;(d=++p&&d&&d[m]||(f=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==v:1!==d.nodeType)||!++f||(y&&((d[F]||(d[F]={}))[e]=[V,f]),d!==t)););return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=N.pseudos[e]||N.setFilters[e.toLowerCase()]||a.error("unsupported pseudo: "+e);return r[F]?r(t):r.length>1?(n=[e,e,"",t],N.setFilters.hasOwnProperty(e.toLowerCase())?i(function(e,n){for(var i,o=r(e,t),a=o.length;a--;)i=nt.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:i(function(e){var t=[],n=[],r=k(e.replace(ct,"$1"));return r[F]?i(function(e,t,n,i){for(var o,a=r(e,null,i,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:i(function(e){return function(t){return a(e,t).length>0}}),contains:i(function(e){return function(t){return(t.textContent||t.innerText||E(t)).indexOf(e)>-1}}),lang:i(function(e){return pt.test(e||"")||a.error("unsupported lang: "+e),e=e.replace(wt,_t).toLowerCase(),function(t){var n;do if(n=D?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(e){var t=window.location&&window.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===M},focus:function(e){return e===L.activeElement&&(!L.hasFocus||L.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!N.pseudos.empty(e)},header:function(e){return bt.test(e.nodeName)},input:function(e){return yt.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:u(function(){return[0]}),last:u(function(e,t){return[t-1]}),eq:u(function(e,t,n){return[0>n?n+t:n]}),even:u(function(e,t){for(var n=0;t>n;n+=2)e.push(n);return e}),odd:u(function(e,t){for(var n=1;t>n;n+=2)e.push(n);return e}),lt:u(function(e,t,n){for(var r=0>n?n+t:n;--r>=0;)e.push(r);return e}),gt:u(function(e,t,n){for(var r=0>n?n+t:n;++r<t;)e.push(r);return e})}};for(w in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})N.pseudos[w]=l(w);for(w in{submit:!0,reset:!0})N.pseudos[w]=c(w);return k=a.compile=function(e,t){var n,r=[],i=[],o=j[e+" "];if(!o){for(t||(t=d(e)),n=t.length;n--;)o=v(t[n]),o[F]?r.push(o):i.push(o);o=j(e,y(i,r))}return o},N.pseudos.nth=N.pseudos.eq,x.prototype=N.filters=N.pseudos,N.setFilters=new x,z.sortStable=F.split("").sort(G).join("")===F,B(),[0,0].sort(G),z.detectDuplicates=K,"function"==typeof r&&r.amd?r(function(){return a}):window.Sizzle=a,a}),r(u,[l,c],function(e,n){function r(e){return"undefined"!=typeof e}function i(e){return"string"==typeof e}function o(e){var t,n,r;for(r=g.createElement("div"),t=g.createDocumentFragment(),r.innerHTML=e;n=r.firstChild;)t.appendChild(n);return t}function a(e,t,n){var r;if("string"==typeof t)t=o(t);else if(t.length){for(r=0;r<t.length;r++)a(e,t[r],n);return e}for(r=e.length;r--;)n.call(e[r],t.parentNode?t:t);return e}function s(e,t){return e&&t&&-1!==(" "+e.className+" ").indexOf(" "+t+" ")}function l(e,t){var n;for(e=e||[],"string"==typeof e&&(e=e.split(" ")),t=t||{},n=e.length;n--;)t[e[n]]={};return t}function c(e,t){return new c.fn.init(e,t)}function u(e){var t=arguments,n,r,i;for(r=1;r<t.length;r++){n=t[r];for(i in n)e[i]=n[i]}return e}function d(e){var t=[],n,r;for(n=0,r=e.length;r>n;n++)t[n]=e[n];return t}function f(e,t){var n;if(t.indexOf)return t.indexOf(e);for(n=t.length;n--;)if(t[n]===e)return n;return-1}function p(e,t){var n,r,i,o,a;if(e)if(n=e.length,n===o){for(r in e)if(e.hasOwnProperty(r)&&(a=e[r],t.call(a,a,r)===!1))break}else for(i=0;n>i&&(a=e[i],t.call(a,a,r)!==!1);i++);return e}function h(e,n,r){for(var i=[],o=e[n];o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!c(o).is(r));)1===o.nodeType&&i.push(o),o=o[n];return i}function m(e,t,n,r){for(var i=[];e;e=e[n])r&&e.nodeType!==r||e===t||i.push(e);return i}var g=document,v=Array.prototype.push,y=Array.prototype.slice,b=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,C=e.Event,x=l("fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom"),w=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)},_=/^\s*|\s*$/g,N=function(e){return null===e||e===t?"":(""+e).replace(_,"")};return c.fn=c.prototype={constructor:c,selector:"",length:0,init:function(e,t){var n=this,r,a;if(!e)return n;if(e.nodeType)return n.context=n[0]=e,n.length=1,n;if(i(e)){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:b.exec(e),!r)return c(t||document).find(e);if(r[1])for(a=o(e).firstChild;a;)this.add(a),a=a.nextSibling;else{if(a=g.getElementById(r[2]),a.id!==r[2])return n.find(e);n.length=1,n[0]=a}}else this.add(e);return n},toArray:function(){return d(this)},add:function(e){var t=this;return w(e)?v.apply(t,e):e instanceof c?t.add(e.toArray()):v.call(t,e),t},attr:function(e,n){var i=this;if("object"==typeof e)p(e,function(e,t){i.attr(t,e)});else{if(!r(n))return i[0]&&1===i[0].nodeType?i[0].getAttribute(e):t;this.each(function(){1===this.nodeType&&this.setAttribute(e,n)})}return i},css:function(e,n){var i=this;if("object"==typeof e)p(e,function(e,t){i.css(t,e)});else{if(e=e.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}),!r(n))return i[0]?i[0].style[e]:t;"number"!=typeof n||x[e]||(n+="px"),i.each(function(){var t=this.style;"opacity"===e&&this.runtimeStyle&&"undefined"==typeof this.runtimeStyle.opacity&&(t.filter=""===n?"":"alpha(opacity="+100*n+")");try{t[e]=n}catch(r){}})}return i},remove:function(){for(var e=this,t,n=this.length;n--;)t=e[n],C.clean(t),t.parentNode&&t.parentNode.removeChild(t);return this},empty:function(){for(var e=this,t,n=this.length;n--;)for(t=e[n];t.firstChild;)t.removeChild(t.firstChild);return this},html:function(e){var t=this,n;if(r(e)){for(n=t.length;n--;)t[n].innerHTML=e;return t}return t[0]?t[0].innerHTML:""},text:function(e){var t=this,n;if(r(e)){for(n=t.length;n--;)t[n].innerText=t[0].textContent=e;return t}return t[0]?t[0].innerText||t[0].textContent:""},append:function(){return a(this,arguments,function(e){1===this.nodeType&&this.appendChild(e)})},prepend:function(){return a(this,arguments,function(e){1===this.nodeType&&this.insertBefore(e,this.firstChild)})},before:function(){var e=this;return e[0]&&e[0].parentNode?a(e,arguments,function(e){this.parentNode.insertBefore(e,this.nextSibling)}):e},after:function(){var e=this;return e[0]&&e[0].parentNode?a(e,arguments,function(e){this.parentNode.insertBefore(e,this)}):e},appendTo:function(e){return c(e).append(this),this},addClass:function(e){return this.toggleClass(e,!0)},removeClass:function(e){return this.toggleClass(e,!1)},toggleClass:function(e,t){var n=this;return-1!==e.indexOf(" ")?p(e.split(" "),function(){n.toggleClass(this,t)}):n.each(function(){var n=this,r;s(n,e)!==t&&(r=n.className,t?n.className+=r?" "+e:e:n.className=N((" "+r+" ").replace(" "+e+" "," ")))}),n},hasClass:function(e){return s(this[0],e)},each:function(e){return p(this,e)},on:function(e,t){return this.each(function(){C.bind(this,e,t)})},off:function(e,t){return this.each(function(){C.unbind(this,e,t)})},show:function(){return this.css("display","")},hide:function(){return this.css("display","none")},slice:function(){return new c(y.apply(this,arguments))},eq:function(e){return-1===e?this.slice(e):this.slice(e,+e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},replaceWith:function(e){var t=this;return t[0]&&t[0].parentNode.replaceChild(c(e)[0],t[0]),t},wrap:function(e){return e=c(e)[0],this.each(function(){var t=this,n=e.cloneNode(!1);t.parentNode.insertBefore(n,t),n.appendChild(t)})},unwrap:function(){return this.each(function(){for(var e=this,t=e.firstChild,n;t;)n=t,t=t.nextSibling,e.parentNode.insertBefore(n,e)})},clone:function(){var e=[];return this.each(function(){e.push(this.cloneNode(!0))}),c(e)},find:function(e){var t,n,r=[];for(t=0,n=this.length;n>t;t++)c.find(e,this[t],r);return c(r)},push:v,sort:[].sort,splice:[].splice},u(c,{extend:u,toArray:d,inArray:f,isArray:w,each:p,trim:N,makeMap:l,find:n,expr:n.selectors,unique:n.uniqueSort,text:n.getText,isXMLDoc:n.isXML,contains:n.contains,filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?c.find.matchesSelector(t[0],e)?[t[0]]:[]:c.find.matches(e,t)}}),p({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return h(e,"parentNode")},parentsUntil:function(e,t){return h(e,"parentNode",t)},next:function(e){return m(e,"nextSibling",1)},prev:function(e){return m(e,"previousSibling",1)},nextNodes:function(e){return m(e,"nextSibling")},prevNodes:function(e){return m(e,"previousSibling")},children:function(e){return m(e.firstChild,"nextSibling",1)},contents:function(e){return d(("iframe"===e.nodeName?e.contentDocument||e.contentWindow.document:e).childNodes)}},function(e,t){c.fn[e]=function(n){var r=this,i;if(r.length>1)throw new Error("DomQuery only supports traverse functions on a single node.");return r[0]&&(i=t(r[0],n)),i=c(i),n&&"parentsUntil"!==e?i.filter(n):i}}),c.fn.filter=function(e){return c.filter(e)},c.fn.is=function(e){return!!e&&this.filter(e).length>0},c.fn.init.prototype=c.fn,c}),r(d,[],function(){return function(e,t){function n(e,t,n,r){function i(e){return e=parseInt(e,10).toString(16),e.length>1?e:"0"+e}return"#"+i(t)+i(n)+i(r)}var r=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,i=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,o=/\s*([^:]+):\s*([^;]+);?/g,a=/\s+$/,s,l,c={},u,d="\ufeff"; +for(e=e||{},u=("\\\" \\' \\; \\: ; : "+d).split(" "),l=0;l<u.length;l++)c[u[l]]=d+l,c[d+l]=u[l];return{toHex:function(e){return e.replace(r,n)},parse:function(t){function s(e,t){var n,r,i,o;n=h[e+"-top"+t],n&&(r=h[e+"-right"+t],n==r&&(i=h[e+"-bottom"+t],r==i&&(o=h[e+"-left"+t],i==o&&(h[e+t]=o,delete h[e+"-top"+t],delete h[e+"-right"+t],delete h[e+"-bottom"+t],delete h[e+"-left"+t]))))}function l(e){var t=h[e],n;if(t&&!(t.indexOf(" ")<0)){for(t=t.split(" "),n=t.length;n--;)if(t[n]!==t[0])return!1;return h[e]=t[0],!0}}function u(e,t,n,r){l(t)&&l(n)&&l(r)&&(h[e]=h[t]+" "+h[n]+" "+h[r],delete h[t],delete h[n],delete h[r])}function d(e){return y=!0,c[e]}function f(e,t){return y&&(e=e.replace(/\uFEFF[0-9]/g,function(e){return c[e]})),t||(e=e.replace(/\\([\'\";:])/g,"$1")),e}function p(e,t,n,r,i,o){return(i=i||o)?(i=f(i),"'"+i.replace(/\'/g,"\\'")+"'"):(t=f(t||n||r),b&&(t=b.call(C,t,"style")),"url('"+t.replace(/\'/g,"\\'")+"')")}var h={},m,g,v,y,b=e.url_converter,C=e.url_converter_scope||this;if(t){for(t=t.replace(/\\[\"\';:\uFEFF]/g,d).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(e){return e.replace(/[;:]/g,d)});m=o.exec(t);)g=m[1].replace(a,"").toLowerCase(),v=m[2].replace(a,""),g&&v.length>0&&("font-weight"===g&&"700"===v?v="bold":("color"===g||"background-color"===g)&&(v=v.toLowerCase()),v=v.replace(r,n),v=v.replace(i,p),h[g]=y?f(v,!0):v),o.lastIndex=m.index+m[0].length;s("border",""),s("border","-width"),s("border","-color"),s("border","-style"),s("padding",""),s("margin",""),u("border","border-width","border-style","border-color"),"medium none"===h.border&&delete h.border}return h},serialize:function(e,n){function r(n){var r,o,a,l;if(r=t.styles[n])for(o=0,a=r.length;a>o;o++)n=r[o],l=e[n],l!==s&&l.length>0&&(i+=(i.length>0?" ":"")+n+": "+l+";")}var i="",o,a;if(n&&t&&t.styles)r("*"),r(n);else for(o in e)a=e[o],a!==s&&a.length>0&&(i+=(i.length>0?" ":"")+o+": "+a+";");return i}}}}),r(f,[],function(){return function(e,t){function n(e,n,r,i){var o,a;if(e){if(!i&&e[n])return e[n];if(e!=t){if(o=e[r])return o;for(a=e.parentNode;a&&a!=t;a=a.parentNode)if(o=a[r])return o}}}var r=e;this.current=function(){return r},this.next=function(e){return r=n(r,"firstChild","nextSibling",e)},this.prev=function(e){return r=n(r,"lastChild","previousSibling",e)}}}),r(p,[],function(){function e(e,n){return n?"array"==n&&g(e)?!0:typeof e==n:e!==t}function n(e){var t=[],n,r;for(n=0,r=e.length;r>n;n++)t[n]=e[n];return t}function r(e,t,n){var r;for(e=e||[],t=t||",","string"==typeof e&&(e=e.split(t)),n=n||{},r=e.length;r--;)n[e[r]]={};return n}function i(e,n,r){var i,o;if(!e)return 0;if(r=r||e,e.length!==t){for(i=0,o=e.length;o>i;i++)if(n.call(r,e[i],i,e)===!1)return 0}else for(i in e)if(e.hasOwnProperty(i)&&n.call(r,e[i],i,e)===!1)return 0;return 1}function o(e,t){var n=[];return i(e,function(e){n.push(t(e))}),n}function a(e,t){var n=[];return i(e,function(e){(!t||t(e))&&n.push(e)}),n}function s(e,t,n){var r=this,i,o,a,s,l,c=0;if(e=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(e),a=e[3].match(/(^|\.)(\w+)$/i)[2],o=r.createNS(e[3].replace(/\.\w+$/,""),n),!o[a]){if("static"==e[2])return o[a]=t,this.onCreate&&this.onCreate(e[2],e[3],o[a]),void 0;t[a]||(t[a]=function(){},c=1),o[a]=t[a],r.extend(o[a].prototype,t),e[5]&&(i=r.resolve(e[5]).prototype,s=e[5].match(/\.(\w+)$/i)[1],l=o[a],o[a]=c?function(){return i[s].apply(this,arguments)}:function(){return this.parent=i[s],l.apply(this,arguments)},o[a].prototype[a]=o[a],r.each(i,function(e,t){o[a].prototype[t]=i[t]}),r.each(t,function(e,t){i[t]?o[a].prototype[t]=function(){return this.parent=i[t],e.apply(this,arguments)}:t!=a&&(o[a].prototype[t]=e)})),r.each(t["static"],function(e,t){o[a][t]=e})}}function l(e,t){var n,r;if(e)for(n=0,r=e.length;r>n;n++)if(e[n]===t)return n;return-1}function c(e,n){var r,i,o,a=arguments,s;for(r=1,i=a.length;i>r;r++){n=a[r];for(o in n)n.hasOwnProperty(o)&&(s=n[o],s!==t&&(e[o]=s))}return e}function u(e,t,n,r){r=r||this,e&&(n&&(e=e[n]),i(e,function(e,i){return t.call(r,e,i,n)===!1?!1:(u(e,t,n,r),void 0)}))}function d(e,t){var n,r;for(t=t||window,e=e.split("."),n=0;n<e.length;n++)r=e[n],t[r]||(t[r]={}),t=t[r];return t}function f(e,t){var n,r;for(t=t||window,e=e.split("."),n=0,r=e.length;r>n&&(t=t[e[n]],t);n++);return t}function p(t,n){return!t||e(t,"array")?t:o(t.split(n||","),m)}var h=/^\s*|\s*$/g,m=function(e){return null===e||e===t?"":(""+e).replace(h,"")},g=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};return{trim:m,isArray:g,is:e,toArray:n,makeMap:r,each:i,map:o,grep:a,inArray:l,extend:c,create:s,walk:u,createNS:d,resolve:f,explode:p}}),r(h,[p],function(e){function t(n){function r(){return H.createDocumentFragment()}function i(e,t){_(F,e,t)}function o(e,t){_(W,e,t)}function a(e){i(e.parentNode,j(e))}function s(e){i(e.parentNode,j(e)+1)}function l(e){o(e.parentNode,j(e))}function c(e){o(e.parentNode,j(e)+1)}function u(e){e?(D[U]=D[V],D[q]=D[z]):(D[V]=D[U],D[z]=D[q]),D.collapsed=F}function d(e){a(e),c(e)}function f(e){i(e,0),o(e,1===e.nodeType?e.childNodes.length:e.nodeValue.length)}function p(e,t){var n=D[V],r=D[z],i=D[U],o=D[q],a=t.startContainer,s=t.startOffset,l=t.endContainer,c=t.endOffset;return 0===e?w(n,r,a,s):1===e?w(i,o,a,s):2===e?w(i,o,l,c):3===e?w(n,r,l,c):void 0}function h(){N(I)}function m(){return N(P)}function g(){return N(O)}function v(e){var t=this[V],r=this[z],i,o;3!==t.nodeType&&4!==t.nodeType||!t.nodeValue?(t.childNodes.length>0&&(o=t.childNodes[r]),o?t.insertBefore(e,o):t.appendChild(e)):r?r>=t.nodeValue.length?n.insertAfter(e,t):(i=t.splitText(r),t.parentNode.insertBefore(e,i)):t.parentNode.insertBefore(e,t)}function y(e){var t=D.extractContents();D.insertNode(e),e.appendChild(t),D.selectNode(e)}function b(){return $(new t(n),{startContainer:D[V],startOffset:D[z],endContainer:D[U],endOffset:D[q],collapsed:D.collapsed,commonAncestorContainer:D.commonAncestorContainer})}function C(e,t){var n;if(3==e.nodeType)return e;if(0>t)return e;for(n=e.firstChild;n&&t>0;)--t,n=n.nextSibling;return n?n:e}function x(){return D[V]==D[U]&&D[z]==D[q]}function w(e,t,r,i){var o,a,s,l,c,u;if(e==r)return t==i?0:i>t?-1:1;for(o=r;o&&o.parentNode!=e;)o=o.parentNode;if(o){for(a=0,s=e.firstChild;s!=o&&t>a;)a++,s=s.nextSibling;return a>=t?-1:1}for(o=e;o&&o.parentNode!=r;)o=o.parentNode;if(o){for(a=0,s=r.firstChild;s!=o&&i>a;)a++,s=s.nextSibling;return i>a?-1:1}for(l=n.findCommonAncestor(e,r),c=e;c&&c.parentNode!=l;)c=c.parentNode;for(c||(c=l),u=r;u&&u.parentNode!=l;)u=u.parentNode;if(u||(u=l),c==u)return 0;for(s=l.firstChild;s;){if(s==c)return-1;if(s==u)return 1;s=s.nextSibling}}function _(e,t,r){var i,o;for(e?(D[V]=t,D[z]=r):(D[U]=t,D[q]=r),i=D[U];i.parentNode;)i=i.parentNode;for(o=D[V];o.parentNode;)o=o.parentNode;o==i?w(D[V],D[z],D[U],D[q])>0&&D.collapse(e):D.collapse(e),D.collapsed=x(),D.commonAncestorContainer=n.findCommonAncestor(D[V],D[U])}function N(e){var t,n=0,r=0,i,o,a,s,l,c;if(D[V]==D[U])return E(e);for(t=D[U],i=t.parentNode;i;t=i,i=i.parentNode){if(i==D[V])return S(t,e);++n}for(t=D[V],i=t.parentNode;i;t=i,i=i.parentNode){if(i==D[U])return k(t,e);++r}for(o=r-n,a=D[V];o>0;)a=a.parentNode,o--;for(s=D[U];0>o;)s=s.parentNode,o++;for(l=a.parentNode,c=s.parentNode;l!=c;l=l.parentNode,c=c.parentNode)a=l,s=c;return T(a,s,e)}function E(e){var t,n,i,o,a,s,l,c,u;if(e!=I&&(t=r()),D[z]==D[q])return t;if(3==D[V].nodeType){if(n=D[V].nodeValue,i=n.substring(D[z],D[q]),e!=O&&(o=D[V],c=D[z],u=D[q]-D[z],0===c&&u>=o.nodeValue.length-1?o.parentNode.removeChild(o):o.deleteData(c,u),D.collapse(F)),e==I)return;return i.length>0&&t.appendChild(H.createTextNode(i)),t}for(o=C(D[V],D[z]),a=D[q]-D[z];o&&a>0;)s=o.nextSibling,l=L(o,e),t&&t.appendChild(l),--a,o=s;return e!=O&&D.collapse(F),t}function S(e,t){var n,i,o,a,s,l;if(t!=I&&(n=r()),i=R(e,t),n&&n.appendChild(i),o=j(e),a=o-D[z],0>=a)return t!=O&&(D.setEndBefore(e),D.collapse(W)),n;for(i=e.previousSibling;a>0;)s=i.previousSibling,l=L(i,t),n&&n.insertBefore(l,n.firstChild),--a,i=s;return t!=O&&(D.setEndBefore(e),D.collapse(W)),n}function k(e,t){var n,i,o,a,s,l;for(t!=I&&(n=r()),o=A(e,t),n&&n.appendChild(o),i=j(e),++i,a=D[q]-i,o=e.nextSibling;o&&a>0;)s=o.nextSibling,l=L(o,t),n&&n.appendChild(l),--a,o=s;return t!=O&&(D.setStartAfter(e),D.collapse(F)),n}function T(e,t,n){var i,o,a,s,l,c,u,d;for(n!=I&&(o=r()),i=A(e,n),o&&o.appendChild(i),a=e.parentNode,s=j(e),l=j(t),++s,c=l-s,u=e.nextSibling;c>0;)d=u.nextSibling,i=L(u,n),o&&o.appendChild(i),u=d,--c;return i=R(t,n),o&&o.appendChild(i),n!=O&&(D.setStartAfter(e),D.collapse(F)),o}function R(e,t){var n=C(D[U],D[q]-1),r,i,o,a,s,l=n!=D[U];if(n==e)return B(n,l,W,t);for(r=n.parentNode,i=B(r,W,W,t);r;){for(;n;)o=n.previousSibling,a=B(n,l,W,t),t!=I&&i.insertBefore(a,i.firstChild),l=F,n=o;if(r==e)return i;n=r.previousSibling,r=r.parentNode,s=B(r,W,W,t),t!=I&&s.appendChild(i),i=s}}function A(e,t){var n=C(D[V],D[z]),r=n!=D[V],i,o,a,s,l;if(n==e)return B(n,r,F,t);for(i=n.parentNode,o=B(i,W,F,t);i;){for(;n;)a=n.nextSibling,s=B(n,r,F,t),t!=I&&o.appendChild(s),r=F,n=a;if(i==e)return o;n=i.nextSibling,i=i.parentNode,l=B(i,W,F,t),t!=I&&l.appendChild(o),o=l}}function B(e,t,r,i){var o,a,s,l,c;if(t)return L(e,i);if(3==e.nodeType){if(o=e.nodeValue,r?(l=D[z],a=o.substring(l),s=o.substring(0,l)):(l=D[q],a=o.substring(0,l),s=o.substring(l)),i!=O&&(e.nodeValue=s),i==I)return;return c=n.clone(e,W),c.nodeValue=a,c}if(i!=I)return n.clone(e,W)}function L(e,t){return t!=I?t==O?n.clone(e,F):e:(e.parentNode.removeChild(e),void 0)}function M(){return n.create("body",null,g()).outerText}var D=this,H=n.doc,P=0,O=1,I=2,F=!0,W=!1,z="startOffset",V="startContainer",U="endContainer",q="endOffset",$=e.extend,j=n.nodeIndex;return $(D,{startContainer:H,startOffset:0,endContainer:H,endOffset:0,collapsed:F,commonAncestorContainer:H,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:i,setEnd:o,setStartBefore:a,setStartAfter:s,setEndBefore:l,setEndAfter:c,collapse:u,selectNode:d,selectNodeContents:f,compareBoundaryPoints:p,deleteContents:h,extractContents:m,cloneContents:g,insertNode:v,surroundContents:y,cloneRange:b,toStringIE:M}),D}return t.prototype.toString=function(){return this.toStringIE()},t}),r(m,[p],function(e){function t(e){var t;return t=document.createElement("div"),t.innerHTML=e,t.textContent||t.innerText||e}function n(e,t){var n,r,i,a={};if(e){for(e=e.split(","),t=t||10,n=0;n<e.length;n+=2)r=String.fromCharCode(parseInt(e[n],t)),o[r]||(i="&"+e[n+1]+";",a[r]=i,a[i]=r);return a}}var r=e.makeMap,i,o,a,s=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,l=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,c=/[<>&\"\']/g,u=/&(#x|#)?([\w]+);/g,d={128:"\u20ac",130:"\u201a",131:"\u0192",132:"\u201e",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02c6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017d",145:"\u2018",146:"\u2019",147:"\u201c",148:"\u201d",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02dc",153:"\u2122",154:"\u0161",155:"\u203a",156:"\u0153",158:"\u017e",159:"\u0178"};o={'"':""","'":"'","<":"<",">":">","&":"&"},a={"<":"<",">":">","&":"&",""":'"',"'":"'"},i=n("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32);var f={encodeRaw:function(e,t){return e.replace(t?s:l,function(e){return o[e]||e})},encodeAllRaw:function(e){return(""+e).replace(c,function(e){return o[e]||e})},encodeNumeric:function(e,t){return e.replace(t?s:l,function(e){return e.length>1?"&#"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+";":o[e]||"&#"+e.charCodeAt(0)+";"})},encodeNamed:function(e,t,n){return n=n||i,e.replace(t?s:l,function(e){return o[e]||n[e]||e})},getEncodeFunc:function(e,t){function a(e,n){return e.replace(n?s:l,function(e){return o[e]||t[e]||"&#"+e.charCodeAt(0)+";"||e})}function c(e,n){return f.encodeNamed(e,n,t)}return t=n(t)||i,e=r(e.replace(/\+/g,",")),e.named&&e.numeric?a:e.named?t?c:f.encodeNamed:e.numeric?f.encodeNumeric:f.encodeRaw},decode:function(e){return e.replace(u,function(e,n,r){return n?(r=parseInt(r,2===n.length?16:10),r>65535?(r-=65536,String.fromCharCode(55296+(r>>10),56320+(1023&r))):d[r]||String.fromCharCode(r)):a[e]||i[e]||t(e)})}};return f}),r(g,[],function(){var e=navigator,t=e.userAgent,n,r,i,o,a,s;n=window.opera&&window.opera.buildNumber,r=/WebKit/.test(t),i=!r&&!n&&/MSIE/gi.test(t)&&/Explorer/gi.test(e.appName),i=i&&/MSIE (\w+)\./.exec(t)[1],o=!r&&/Gecko/.test(t),a=-1!=t.indexOf("Mac"),s=/(iPad|iPhone)/.test(t);var l=!s||t.match(/AppleWebKit\/(\d*)/)[1]>=534;return{opera:n,webkit:r,ie:i,gecko:o,mac:a,iOS:s,contentEditable:l,transparentSrc:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",caretAfter:8!=i,range:window.getSelection&&"Range"in window,documentMode:i?document.documentMode||7:10}}),r(v,[c,d,l,f,h,m,g,p],function(e,n,r,i,o,a,s,l){function c(e,t){var i=this,o;i.doc=e,i.win=window,i.files={},i.counter=0,i.stdMode=!g||e.documentMode>=8,i.boxModel=!g||"CSS1Compat"==e.compatMode||i.stdMode,i.hasOuterHTML="outerHTML"in e.createElement("a"),i.settings=t=h({keep_values:!1,hex_colors:1},t),i.schema=t.schema,i.styles=new n({url_converter:t.url_converter,url_converter_scope:t.url_converter_scope},t.schema),i.fixDoc(e),i.events=t.ownEvents?new r(t.proxy):r.Event,o=t.schema?t.schema.getBlockElements():{},i.isBlock=function(e){if(!e)return!1;var t=e.nodeType;return t?!(1!==t||!o[e.nodeName]):!!o[e]}}var u=l.each,d=l.is,f=l.grep,p=l.trim,h=l.extend,m=s.webkit,g=s.ie,v=/^([a-z0-9],?)+$/i,y=/^[ \t\r\n]*$/,b=l.makeMap("fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom"," ");return c.prototype={root:null,props:{"for":"htmlFor","class":"className",className:"className",checked:"checked",disabled:"disabled",maxlength:"maxLength",readonly:"readOnly",selected:"selected",value:"value",id:"id",name:"name",type:"type"},fixDoc:function(e){var t=this.settings,n;if(g&&t.schema){"abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video".replace(/\w+/g,function(t){e.createElement(t)});for(n in t.schema.getCustomElements())e.createElement(n)}},clone:function(e,t){var n=this,r,i;return!g||1!==e.nodeType||t?e.cloneNode(t):(i=n.doc,t?r.firstChild:(r=i.createElement(e.nodeName),u(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),r))},getRoot:function(){var e=this;return e.get(e.settings.root_element)||e.doc.body},getViewPort:function(e){var t,n;return e=e?e:this.win,t=e.document,n=this.boxModel?t.documentElement:t.body,{x:e.pageXOffset||n.scrollLeft,y:e.pageYOffset||n.scrollTop,w:e.innerWidth||n.clientWidth,h:e.innerHeight||n.clientHeight}},getRect:function(e){var t=this,n,r;return e=t.get(e),n=t.getPos(e),r=t.getSize(e),{x:n.x,y:n.y,w:r.w,h:r.h}},getSize:function(e){var t=this,n,r;return e=t.get(e),n=t.getStyle(e,"width"),r=t.getStyle(e,"height"),-1===n.indexOf("px")&&(n=0),-1===r.indexOf("px")&&(r=0),{w:parseInt(n,10)||e.offsetWidth||e.clientWidth,h:parseInt(r,10)||e.offsetHeight||e.clientHeight}},getParent:function(e,t,n){return this.getParents(e,t,n,!1)},getParents:function(e,n,r,i){var o=this,a,s=[];for(e=o.get(e),i=i===t,r=r||("BODY"!=o.getRoot().nodeName?o.getRoot().parentNode:null),d(n,"string")&&(a=n,n="*"===n?function(e){return 1==e.nodeType}:function(e){return o.is(e,a)});e&&e!=r&&e.nodeType&&9!==e.nodeType;){if(!n||n(e)){if(!i)return e;s.push(e)}e=e.parentNode}return i?s:null},get:function(e){var t;return e&&this.doc&&"string"==typeof e&&(t=e,e=this.doc.getElementById(e),e&&e.id!==t)?this.doc.getElementsByName(t)[1]:e},getNext:function(e,t){return this._findSib(e,t,"nextSibling")},getPrev:function(e,t){return this._findSib(e,t,"previousSibling")},select:function(t,n){var r=this;return e(t,r.get(n)||r.get(r.settings.root_element)||r.doc,[])},is:function(n,r){var i;if(n.length===t){if("*"===r)return 1==n.nodeType;if(v.test(r)){for(r=r.toLowerCase().split(/,/),n=n.nodeName.toLowerCase(),i=r.length-1;i>=0;i--)if(r[i]==n)return!0;return!1}}return n.nodeType&&1!=n.nodeType?!1:e.matches(r,n.nodeType?[n]:n).length>0},add:function(e,t,n,r,i){var o=this;return this.run(e,function(e){var a;return a=d(t,"string")?o.doc.createElement(t):t,o.setAttribs(a,n),r&&(r.nodeType?a.appendChild(r):o.setHTML(a,r)),i?a:e.appendChild(a)})},create:function(e,t,n){return this.add(this.doc.createElement(e),e,t,n,1)},createHTML:function(e,t,n){var r="",i;r+="<"+e;for(i in t)t.hasOwnProperty(i)&&null!==t[i]&&(r+=" "+i+'="'+this.encode(t[i])+'"');return"undefined"!=typeof n?r+">"+n+"</"+e+">":r+" />"},createFragment:function(e){var t,n,r=this.doc,i;for(i=r.createElement("div"),t=r.createDocumentFragment(),e&&(i.innerHTML=e);n=i.firstChild;)t.appendChild(n);return t},remove:function(e,t){return this.run(e,function(e){var n,r=e.parentNode;if(!r)return null;if(t)for(;n=e.firstChild;)!g||3!==n.nodeType||n.nodeValue?r.insertBefore(n,e):e.removeChild(n);return r.removeChild(e)})},setStyle:function(e,t,n){return this.run(e,function(e){var r=this,i,o;if(t)if("string"==typeof t){i=e.style,t=t.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}),"number"!=typeof n||b[t]||(n+="px"),"opacity"===t&&e.runtimeStyle&&"undefined"==typeof e.runtimeStyle.opacity&&(i.filter=""===n?"":"alpha(opacity="+100*n+")"),"float"==t&&(t="cssFloat"in e.style?"cssFloat":"styleFloat");try{i[t]=n}catch(a){}r.settings.update_styles&&e.removeAttribute("data-mce-style")}else for(o in t)r.setStyle(e,o,t[o])})},getStyle:function(e,n,r){if(e=this.get(e)){if(this.doc.defaultView&&r){n=n.replace(/[A-Z]/g,function(e){return"-"+e});try{return this.doc.defaultView.getComputedStyle(e,null).getPropertyValue(n)}catch(i){return null}}return n=n.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}),"float"==n&&(n=g?"styleFloat":"cssFloat"),n.currentStyle&&r?e.currentStyle[n]:e.style?e.style[n]:t}},setStyles:function(e,t){this.setStyle(e,t)},css:function(e,t,n){this.setStyle(e,t,n)},removeAllAttribs:function(e){return this.run(e,function(e){var t,n=e.attributes;for(t=n.length-1;t>=0;t--)e.removeAttributeNode(n.item(t))})},setAttrib:function(e,t,n){var r=this;if(e&&t)return this.run(e,function(e){var i=r.settings,o=e.getAttribute(t);if(null!==n)switch(t){case"style":if(!d(n,"string"))return u(n,function(t,n){r.setStyle(e,n,t)}),void 0;i.keep_values&&(n?e.setAttribute("data-mce-style",n,2):e.removeAttribute("data-mce-style",2)),e.style.cssText=n;break;case"class":e.className=n||"";break;case"src":case"href":i.keep_values&&(i.url_converter&&(n=i.url_converter.call(i.url_converter_scope||r,n,t,e)),r.setAttrib(e,"data-mce-"+t,n,2));break;case"shape":e.setAttribute("data-mce-style",n)}d(n)&&null!==n&&0!==n.length?e.setAttribute(t,""+n,2):e.removeAttribute(t,2),o!=n&&i.onSetAttrib&&i.onSetAttrib({attrElm:e,attrName:t,attrValue:n})})},setAttribs:function(e,t){var n=this;return this.run(e,function(e){u(t,function(t,r){n.setAttrib(e,r,t)})})},getAttrib:function(e,t,n){var r,i=this,o;if(e=i.get(e),!e||1!==e.nodeType)return n===o?!1:n;if(d(n)||(n=""),/^(src|href|style|coords|shape)$/.test(t)&&(r=e.getAttribute("data-mce-"+t)))return r;if(g&&i.props[t]&&(r=e[i.props[t]],r=r&&r.nodeValue?r.nodeValue:r),r||(r=e.getAttribute(t,2)),/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(t))return e[i.props[t]]===!0&&""===r?t:r?t:"";if("FORM"===e.nodeName&&e.getAttributeNode(t))return e.getAttributeNode(t).nodeValue;if("style"===t&&(r=r||e.style.cssText,r&&(r=i.serializeStyle(i.parseStyle(r),e.nodeName),i.settings.keep_values&&e.setAttribute("data-mce-style",r))),m&&"class"===t&&r&&(r=r.replace(/(apple|webkit)\-[a-z\-]+/gi,"")),g)switch(t){case"rowspan":case"colspan":1===r&&(r="");break;case"size":("+0"===r||20===r||0===r)&&(r="");break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":0===r&&(r="");break;case"hspace":-1===r&&(r="");break;case"maxlength":case"tabindex":(32768===r||2147483647===r||"32768"===r)&&(r="");break;case"multiple":case"compact":case"noshade":case"nowrap":return 65535===r?t:n;case"shape":r=r.toLowerCase();break;default:0===t.indexOf("on")&&r&&(r=(""+r).replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1"))}return r!==o&&null!==r&&""!==r?""+r:n},getPos:function(e,t){var n=this,r=0,i=0,o,a=n.doc,s;if(e=n.get(e),t=t||a.body,e){if(t===a.body&&e.getBoundingClientRect)return s=e.getBoundingClientRect(),t=n.boxModel?a.documentElement:a.body,r=s.left+(a.documentElement.scrollLeft||a.body.scrollLeft)-t.clientTop,i=s.top+(a.documentElement.scrollTop||a.body.scrollTop)-t.clientLeft,{x:r,y:i};for(o=e;o&&o!=t&&o.nodeType;)r+=o.offsetLeft||0,i+=o.offsetTop||0,o=o.offsetParent;for(o=e.parentNode;o&&o!=t&&o.nodeType;)r-=o.scrollLeft||0,i-=o.scrollTop||0,o=o.parentNode}return{x:r,y:i}},parseStyle:function(e){return this.styles.parse(e)},serializeStyle:function(e,t){return this.styles.serialize(e,t)},addStyle:function(e){var t=this,n=t.doc,r,i;if(t!==c.DOM&&n===document){var o=c.DOM.addedStyles;if(o=o||[],o[e])return;o[e]=!0,c.DOM.addedStyles=o}i=n.getElementById("mceDefaultStyles"),i||(i=n.createElement("style"),i.id="mceDefaultStyles",i.type="text/css",r=n.getElementsByTagName("head")[0],r.firstChild?r.insertBefore(i,r.firstChild):r.appendChild(i)),i.styleSheet?i.styleSheet.cssText+=e:i.appendChild(n.createTextNode(e))},loadCSS:function(e){var t=this,n=t.doc,r;return t!==c.DOM&&n===document?(c.DOM.loadCSS(e),void 0):(e||(e=""),r=n.getElementsByTagName("head")[0],u(e.split(","),function(e){var i;t.files[e]||(t.files[e]=!0,i=t.create("link",{rel:"stylesheet",href:e}),g&&n.documentMode&&n.recalc&&(i.onload=function(){n.recalc&&n.recalc(),i.onload=null}),r.appendChild(i))}),void 0)},addClass:function(e,t){return this.run(e,function(e){var n;return t?this.hasClass(e,t)?e.className:(n=this.removeClass(e,t),e.className=n=(""!==n?n+" ":"")+t,n):0})},removeClass:function(e,t){var n=this,r;return n.run(e,function(e){var i;return n.hasClass(e,t)?(r||(r=new RegExp("(^|\\s+)"+t+"(\\s+|$)","g")),i=e.className.replace(r," "),i=p(" "!=i?i:""),e.className=i,i||(e.removeAttribute("class"),e.removeAttribute("className")),i):e.className})},hasClass:function(e,t){return e=this.get(e),e&&t?-1!==(" "+e.className+" ").indexOf(" "+t+" "):!1},toggleClass:function(e,n,r){r=r===t?!this.hasClass(e,n):r,this.hasClass(e,n)!==r&&(r?this.addClass(e,n):this.removeClass(e,n))},show:function(e){return this.setStyle(e,"display","block")},hide:function(e){return this.setStyle(e,"display","none")},isHidden:function(e){return e=this.get(e),!e||"none"==e.style.display||"none"==this.getStyle(e,"display")},uniqueId:function(e){return(e?e:"mce_")+this.counter++},setHTML:function(e,t){var n=this;return n.run(e,function(e){if(g){for(;e.firstChild;)e.removeChild(e.firstChild);try{e.innerHTML="<br />"+t,e.removeChild(e.firstChild)}catch(r){var i=n.create("div");i.innerHTML="<br />"+t,u(f(i.childNodes),function(t,n){n&&e.canHaveHTML&&e.appendChild(t)})}}else e.innerHTML=t;return t})},getOuterHTML:function(e){var t,n=this;return(e=n.get(e))?1===e.nodeType&&n.hasOuterHTML?e.outerHTML:(t=(e.ownerDocument||n.doc).createElement("body"),t.appendChild(e.cloneNode(!0)),t.innerHTML):null},setOuterHTML:function(e,t,n){var r=this;return r.run(e,function(e){function i(){var i,o;for(o=n.createElement("body"),o.innerHTML=t,i=o.lastChild;i;)r.insertAfter(i.cloneNode(!0),e),i=i.previousSibling;r.remove(e)}if(1==e.nodeType)if(n=n||e.ownerDocument||r.doc,g)try{1==e.nodeType&&r.hasOuterHTML?e.outerHTML=t:i()}catch(o){i()}else i()})},decode:a.decode,encode:a.encodeAllRaw,insertAfter:function(e,t){return t=this.get(t),this.run(e,function(e){var n,r;return n=t.parentNode,r=t.nextSibling,r?n.insertBefore(e,r):n.appendChild(e),e})},replace:function(e,t,n){var r=this;return r.run(t,function(t){return d(t,"array")&&(e=e.cloneNode(!0)),n&&u(f(t.childNodes),function(t){e.appendChild(t)}),t.parentNode.replaceChild(e,t)})},rename:function(e,t){var n=this,r;return e.nodeName!=t.toUpperCase()&&(r=n.create(t),u(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),n.replace(r,e,1)),r||e},findCommonAncestor:function(e,t){for(var n=e,r;n;){for(r=t;r&&n!=r;)r=r.parentNode;if(n==r)break;n=n.parentNode}return!n&&e.ownerDocument?e.ownerDocument.documentElement:n},toHex:function(e){return this.styles.toHex(l.trim(e))},getClasses:function(){function e(t){u(t.imports,function(t){e(t)}),u(t.cssRules||t.rules,function(t){switch(t.type||1){case 1:t.selectorText&&u(t.selectorText.split(","),function(e){e=e.replace(/^\s*|\s*$|^\s\./g,""),!/\.mce/.test(e)&&/\.[\w\-]+$/.test(e)&&(o=e,e=e.replace(/.*\.([a-z0-9_\-]+).*/i,"$1"),(!i||(e=i(e,o)))&&(r[e]||(n.push({"class":e}),r[e]=1)))});break;case 3:e(t.styleSheet)}})}var t=this,n=[],r={},i=t.settings.class_filter,o;if(t.classes)return t.classes;try{u(t.doc.styleSheets,e)}catch(a){}return n.length>0&&(t.classes=n),n},run:function(e,t,n){var r=this,i;return"string"==typeof e&&(e=r.get(e)),e?(n=n||this,e.nodeType||!e.length&&0!==e.length?t.call(n,e):(i=[],u(e,function(e,o){e&&("string"==typeof e&&(e=r.get(e)),i.push(t.call(n,e,o)))}),i)):!1},getAttribs:function(e){var t;if(e=this.get(e),!e)return[];if(g){if(t=[],"OBJECT"==e.nodeName)return e.attributes;"OPTION"===e.nodeName&&this.getAttrib(e,"selected")&&t.push({specified:1,nodeName:"selected"});var n=/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi;return e.cloneNode(!1).outerHTML.replace(n,"").replace(/[\w:\-]+/gi,function(e){t.push({specified:1,nodeName:e})}),t}return e.attributes},isEmpty:function(e,t){var n=this,r,o,a,s,l,c=0;if(e=e.firstChild){s=new i(e,e.parentNode),t=t||n.schema?n.schema.getNonEmptyElements():null;do{if(a=e.nodeType,1===a){if(e.getAttribute("data-mce-bogus"))continue;if(l=e.nodeName.toLowerCase(),t&&t[l]){if("br"===l){c++;continue}return!1}for(o=n.getAttribs(e),r=e.attributes.length;r--;)if(l=e.attributes[r].nodeName,"name"===l||"data-mce-bookmark"===l)return!1}if(8==a)return!1;if(3===a&&!y.test(e.nodeValue))return!1}while(e=s.next())}return 1>=c},createRng:function(){var e=this.doc;return e.createRange?e.createRange():new o(this)},nodeIndex:function(e,t){var n=0,r,i,o;if(e)for(r=e.nodeType,e=e.previousSibling,i=e;e;e=e.previousSibling)o=e.nodeType,(!t||3!=o||o!=r&&e.nodeValue.length)&&(n++,r=o);return n},split:function(e,t,n){function r(e){function t(e){var t=e.previousSibling&&"SPAN"==e.previousSibling.nodeName,n=e.nextSibling&&"SPAN"==e.nextSibling.nodeName;return t&&n}var n,o=e.childNodes,a=e.nodeType;if(1!=a||"bookmark"!=e.getAttribute("data-mce-type")){for(n=o.length-1;n>=0;n--)r(o[n]);if(9!=a){if(3==a&&e.nodeValue.length>0){var s=p(e.nodeValue).length;if(!i.isBlock(e.parentNode)||s>0||0===s&&t(e))return}else if(1==a&&(o=e.childNodes,1==o.length&&o[0]&&1==o[0].nodeType&&"bookmark"==o[0].getAttribute("data-mce-type")&&e.parentNode.insertBefore(o[0],e),o.length||/^(br|hr|input|img)$/i.test(e.nodeName)))return;i.remove(e)}return e}}var i=this,o=i.createRng(),a,s,l;return e&&t?(o.setStart(e.parentNode,i.nodeIndex(e)),o.setEnd(t.parentNode,i.nodeIndex(t)),a=o.extractContents(),o=i.createRng(),o.setStart(t.parentNode,i.nodeIndex(t)+1),o.setEnd(e.parentNode,i.nodeIndex(e)+1),s=o.extractContents(),l=e.parentNode,l.insertBefore(r(a),e),n?l.replaceChild(n,t):l.insertBefore(t,e),l.insertBefore(r(s),e),i.remove(e),n||t):void 0},bind:function(e,t,n,r){return this.events.bind(e,t,n,r||this)},unbind:function(e,t,n){return this.events.unbind(e,t,n)},fire:function(e,t,n){return this.events.fire(e,t,n)},getContentEditable:function(e){var t;return 1!=e.nodeType?null:(t=e.getAttribute("data-mce-contenteditable"),t&&"inherit"!==t?t:"inherit"!==e.contentEditable?e.contentEditable:null)},destroy:function(){var e=this;e.win=e.doc=e.root=e.events=e.frag=null},dumpRng:function(e){return"startContainer: "+e.startContainer.nodeName+", startOffset: "+e.startOffset+", endContainer: "+e.endContainer.nodeName+", endOffset: "+e.endOffset},_findSib:function(e,t,n){var r=this,i=t;if(e)for("string"==typeof i&&(i=function(e){return r.is(e,t)}),e=e[n];e;e=e[n])if(i(e))return e;return null}},c.DOM=new c(document),c}),r(y,[v,p],function(e,t){function n(){function e(e,t){function n(){o.remove(s),a&&(a.onreadystatechange=a.onload=a=null),t()}function i(){"undefined"!=typeof console&&console.log&&console.log("Failed to load: "+e)}var o=r,a,s;s=o.uniqueId(),a=document.createElement("script"),a.id=s,a.type="text/javascript",a.src=e,"onreadystatechange"in a?a.onreadystatechange=function(){/loaded|complete/.test(a.readyState)&&n()}:a.onload=n,a.onerror=i,(document.getElementsByTagName("head")[0]||document.body).appendChild(a)}var t=0,n=1,a=2,s={},l=[],c={},u=[],d=0,f;this.isDone=function(e){return s[e]==a},this.markDone=function(e){s[e]=a},this.add=this.load=function(e,n,r){var i=s[e];i==f&&(l.push(e),s[e]=t),n&&(c[e]||(c[e]=[]),c[e].push({func:n,scope:r||this}))},this.loadQueue=function(e,t){this.loadScripts(l,e,t)},this.loadScripts=function(t,r,l){function p(e){i(c[e],function(e){e.func.call(e.scope)}),c[e]=f}var h;u.push({func:r,scope:l||this}),h=function(){var r=o(t);t.length=0,i(r,function(t){return s[t]==a?(p(t),void 0):(s[t]!=n&&(s[t]=n,d++,e(t,function(){s[t]=a,d--,p(t),h()})),void 0)}),d||(i(u,function(e){e.func.call(e.scope)}),u.length=0)},h()}}var r=e.DOM,i=t.each,o=t.grep;return n.ScriptLoader=new n,n}),r(b,[y,p],function(e,n){function r(){var e=this;e.items=[],e.urls={},e.lookup={}}var i=n.each;return r.prototype={get:function(e){return this.lookup[e]?this.lookup[e].instance:t},dependencies:function(e){var t;return this.lookup[e]&&(t=this.lookup[e].dependencies),t||[]},requireLangPack:function(t){var n=r.settings;n&&n.language&&n.language_load!==!1&&e.ScriptLoader.add(this.urls[t]+"/langs/"+n.language+".js")},add:function(e,t,n){return this.items.push(t),this.lookup[e]={instance:t,dependencies:n},t},createUrl:function(e,t){return"object"==typeof t?t:{prefix:e.prefix,resource:t,suffix:e.suffix}},addComponents:function(t,n){var r=this.urls[t]; +i(n,function(t){e.ScriptLoader.add(r+"/"+t)})},load:function(n,o,a,s){function l(){var r=c.dependencies(n);i(r,function(e){var n=c.createUrl(o,e);c.load(n.resource,n,t,t)}),a&&(s?a.call(s):a.call(e))}var c=this,u=o;c.urls[n]||("object"==typeof o&&(u=o.prefix+o.resource+o.suffix),0!==u.indexOf("/")&&-1==u.indexOf("://")&&(u=r.baseURL+"/"+u),c.urls[n]=u.substring(0,u.lastIndexOf("/")),c.lookup[n]?l():e.ScriptLoader.add(u,l,s))}},r.PluginManager=new r,r.ThemeManager=new r,r}),r(C,[],function(){function e(e,t,n){var r,i,o=n?"lastChild":"firstChild",a=n?"prev":"next";if(e[o])return e[o];if(e!==t){if(r=e[a])return r;for(i=e.parent;i&&i!==t;i=i.parent)if(r=i[a])return r}}function t(e,t){this.name=e,this.type=t,1===t&&(this.attributes=[],this.attributes.map={})}var n=/^[ \t\r\n]*$/,r={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};return t.prototype={replace:function(e){var t=this;return e.parent&&e.remove(),t.insert(e,t),t.remove(),t},attr:function(e,t){var n=this,r,i,o;if("string"!=typeof e){for(i in e)n.attr(i,e[i]);return n}if(r=n.attributes){if(t!==o){if(null===t){if(e in r.map)for(delete r.map[e],i=r.length;i--;)if(r[i].name===e)return r=r.splice(i,1),n;return n}if(e in r.map){for(i=r.length;i--;)if(r[i].name===e){r[i].value=t;break}}else r.push({name:e,value:t});return r.map[e]=t,n}return r.map[e]}},clone:function(){var e=this,n=new t(e.name,e.type),r,i,o,a,s;if(o=e.attributes){for(s=[],s.map={},r=0,i=o.length;i>r;r++)a=o[r],"id"!==a.name&&(s[s.length]={name:a.name,value:a.value},s.map[a.name]=a.value);n.attributes=s}return n.value=e.value,n.shortEnded=e.shortEnded,n},wrap:function(e){var t=this;return t.parent.insert(e,t),e.append(t),t},unwrap:function(){var e=this,t,n;for(t=e.firstChild;t;)n=t.next,e.insert(t,e,!0),t=n;e.remove()},remove:function(){var e=this,t=e.parent,n=e.next,r=e.prev;return t&&(t.firstChild===e?(t.firstChild=n,n&&(n.prev=null)):r.next=n,t.lastChild===e?(t.lastChild=r,r&&(r.next=null)):n.prev=r,e.parent=e.next=e.prev=null),e},append:function(e){var t=this,n;return e.parent&&e.remove(),n=t.lastChild,n?(n.next=e,e.prev=n,t.lastChild=e):t.lastChild=t.firstChild=e,e.parent=t,e},insert:function(e,t,n){var r;return e.parent&&e.remove(),r=t.parent||this,n?(t===r.firstChild?r.firstChild=e:t.prev.next=e,e.prev=t.prev,e.next=t,t.prev=e):(t===r.lastChild?r.lastChild=e:t.next.prev=e,e.next=t.next,e.prev=t,t.next=e),e.parent=r,e},getAll:function(t){var n=this,r,i=[];for(r=n.firstChild;r;r=e(r,n))r.name===t&&i.push(r);return i},empty:function(){var t=this,n,r,i;if(t.firstChild){for(n=[],i=t.firstChild;i;i=e(i,t))n.push(i);for(r=n.length;r--;)i=n[r],i.parent=i.firstChild=i.lastChild=i.next=i.prev=null}return t.firstChild=t.lastChild=null,t},isEmpty:function(t){var r=this,i=r.firstChild,o,a;if(i)do{if(1===i.type){if(i.attributes.map["data-mce-bogus"])continue;if(t[i.name])return!1;for(o=i.attributes.length;o--;)if(a=i.attributes[o].name,"name"===a||0===a.indexOf("data-mce-"))return!1}if(8===i.type)return!1;if(3===i.type&&!n.test(i.value))return!1}while(i=e(i,r));return!0},walk:function(t){return e(this,null,t)}},t.create=function(e,n){var i,o;if(i=new t(e,r[e]||1),n)for(o in n)i.attr(o,n[o]);return i},t}),r(x,[p],function(e){function t(e,t){return e?e.split(t||" "):[]}function n(e){function n(e,n,r){function i(e){var t={},n,r;for(n=0,r=e.length;r>n;n++)t[e[n]]={};return t}var o,l,c,u=arguments;for(r=r||[],n=n||"","string"==typeof r&&(r=t(r)),l=3;l<u.length;l++)"string"==typeof u[l]&&(u[l]=t(u[l])),r.push.apply(r,u[l]);for(e=t(e),o=e.length;o--;)c=[].concat(s,t(n)),a[e[o]]={attributes:i(c),attributesOrder:c,children:i(r)}}function i(e,n){var r,i,o,s;for(e=t(e),r=e.length,n=t(n);r--;)for(i=a[e[r]],o=0,s=n.length;s>o;o++)i.attributes[n[o]]={},i.attributesOrder.push(n[o])}var a={},s,l,c,u,d,f,p;return r[e]?r[e]:(s=t("id accesskey class dir lang style tabindex title"),l=t("onabort onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncontextmenu oncuechange ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onpause onplay onplaying onprogress onratechange onreset onscroll onseeked onseeking onseeking onselect onshow onstalled onsubmit onsuspend ontimeupdate onvolumechange onwaiting"),c=t("address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul"),u=t("a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd label map noscript object q s samp script select small span strong sub sup textarea u var #text #comment"),"html4"!=e&&(s.push.apply(s,t("contenteditable contextmenu draggable dropzone hidden spellcheck translate")),c.push.apply(c,t("article aside details dialog figure header footer hgroup section nav")),u.push.apply(u,t("audio canvas command datalist mark meter output progress time wbr video ruby bdi keygen"))),"html5-strict"!=e&&(s.push("xml:lang"),p=t("acronym applet basefont big font strike tt"),u.push.apply(u,p),o(p,function(e){n(e,"",u)}),f=t("center dir isindex noframes"),c.push.apply(c,f),d=[].concat(c,u),o(f,function(e){n(e,"",d)})),d=d||[].concat(c,u),n("html","manifest","head body"),n("head","","base command link meta noscript script style title"),n("title hr noscript br"),n("base","href target"),n("link","href rel media hreflang type sizes hreflang"),n("meta","name http-equiv content charset"),n("style","media type scoped"),n("script","src async defer type charset"),n("body","onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onscroll onstorage onunload",d),n("address dt dd div caption","",d),n("h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn","",u),n("blockquote","cite",d),n("ol","reversed start type","li"),n("ul","","li"),n("li","value",d),n("dl","","dt dd"),n("a","href target rel media hreflang type",u),n("q","cite",u),n("ins del","cite datetime",d),n("img","src alt usemap ismap width height"),n("iframe","src name width height",d),n("embed","src type width height"),n("object","data type typemustmatch name usemap form width height",d,"param"),n("param","name value"),n("map","name",d,"area"),n("area","alt coords shape href target rel media hreflang type"),n("table","border","caption colgroup thead tfoot tbody tr"+("html4"==e?" col":"")),n("colgroup","span","col"),n("col","span"),n("tbody thead tfoot","","tr"),n("tr","","td th"),n("td","colspan rowspan headers",d),n("th","colspan rowspan headers scope abbr",d),n("form","accept-charset action autocomplete enctype method name novalidate target",d),n("fieldset","disabled form name",d,"legend"),n("label","form for",u),n("input","accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"),n("button","disabled form formaction formenctype formmethod formnovalidate formtarget name type value","html4"==e?d:u),n("select","disabled form multiple name required size","option optgroup"),n("optgroup","disabled label","option"),n("option","disabled label selected value"),n("textarea","cols dirname disabled form maxlength name readonly required rows wrap"),n("menu","type label",d,"li"),n("noscript","",d),"html4"!=e&&(n("wbr"),n("ruby","",u,"rt rp"),n("figcaption","",d),n("mark rt rp summary bdi","",u),n("canvas","width height",d),n("video","src crossorigin poster preload autoplay mediagroup loop muted controls width height",d,"track source"),n("audio","src crossorigin preload autoplay mediagroup loop muted controls",d,"track source"),n("source","src type media"),n("track","kind src srclang label default"),n("datalist","",u,"option"),n("article section nav aside header footer","",d),n("hgroup","","h1 h2 h3 h4 h5 h6"),n("figure","",d,"figcaption"),n("time","datetime",u),n("dialog","open",d),n("command","type label icon disabled checked radiogroup command"),n("output","for form name",u),n("progress","value max",u),n("meter","value min max low high optimum",u),n("details","open",d,"summary"),n("keygen","autofocus challenge disabled form keytype name")),"html5-strict"!=e&&(i("script","language xml:space"),i("style","xml:space"),i("object","declare classid codebase codetype archive standby align border hspace vspace"),i("param","valuetype type"),i("a","charset name rev shape coords"),i("br","clear"),i("applet","codebase archive code object alt name width height align hspace vspace"),i("img","name longdesc align border hspace vspace"),i("iframe","longdesc frameborder marginwidth marginheight scrolling align"),i("font basefont","size color face"),i("input","usemap align"),i("select","onchange"),i("textarea"),i("h1 h2 h3 h4 h5 h6 div p legend caption","align"),i("ul","type compact"),i("li","type"),i("ol dl menu dir","compact"),i("pre","width xml:space"),i("hr","align noshade size width"),i("isindex","prompt"),i("table","summary width frame rules cellspacing cellpadding align bgcolor"),i("col","width align char charoff valign"),i("colgroup","width align char charoff valign"),i("thead","align char charoff valign"),i("tr","align char charoff valign bgcolor"),i("th","axis align char charoff valign nowrap bgcolor width height"),i("form","accept"),i("td","abbr axis scope align char charoff valign nowrap bgcolor width height"),i("tfoot","align char charoff valign"),i("tbody","align char charoff valign"),i("area","nohref"),i("body","background bgcolor text link vlink alink")),"html4"!=e&&(i("input button select textarea","autofocus"),i("input textarea","placeholder"),i("a","download"),i("link script img","crossorigin"),i("iframe","srcdoc sandbox seamless allowfullscreen")),o(t("a form meter progress dfn"),function(e){a[e]&&delete a[e].children[e]}),delete a.caption.children.table,r[e]=a,a)}var r={},i=e.makeMap,o=e.each,a=e.extend,s=e.explode,l=e.inArray;return function(e){function c(t,n,o){var s=e[t];return s?s=i(s,",",i(s.toUpperCase()," ")):(s=r[t],s||(s=i(n," ",i(n.toUpperCase()," ")),s=a(s,o),r[t]=s)),s}function u(e){return new RegExp("^"+e.replace(/([?+*])/g,".$1")+"$")}function d(e){var n,r,o,a,s,c,d,f,p,h,m,g,y,C,x,w,_,N,E,S=/^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,k=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,T=/[*?+]/;if(e)for(e=t(e,","),v["@"]&&(w=v["@"].attributes,_=v["@"].attributesOrder),n=0,r=e.length;r>n;n++)if(s=S.exec(e[n])){if(C=s[1],p=s[2],x=s[3],f=s[5],g={},y=[],c={attributes:g,attributesOrder:y},"#"===C&&(c.paddEmpty=!0),"-"===C&&(c.removeEmpty=!0),"!"===s[4]&&(c.removeEmptyAttrs=!0),w){for(N in w)g[N]=w[N];y.push.apply(y,_)}if(f)for(f=t(f,"|"),o=0,a=f.length;a>o;o++)if(s=k.exec(f[o])){if(d={},m=s[1],h=s[2].replace(/::/g,":"),C=s[3],E=s[4],"!"===m&&(c.attributesRequired=c.attributesRequired||[],c.attributesRequired.push(h),d.required=!0),"-"===m){delete g[h],y.splice(l(y,h),1);continue}C&&("="===C&&(c.attributesDefault=c.attributesDefault||[],c.attributesDefault.push({name:h,value:E}),d.defaultValue=E),":"===C&&(c.attributesForced=c.attributesForced||[],c.attributesForced.push({name:h,value:E}),d.forcedValue=E),"<"===C&&(d.validValues=i(E,"?"))),T.test(h)?(c.attributePatterns=c.attributePatterns||[],d.pattern=u(h),c.attributePatterns.push(d)):(g[h]||y.push(h),g[h]=d)}w||"@"!=p||(w=g,_=y),x&&(c.outputName=p,v[x]=c),T.test(p)?(c.pattern=u(p),b.push(c)):v[p]=c}}function f(e){v={},b=[],d(e),o(x,function(e,t){y[t]=e.children})}function p(e){var n=/^(~)?(.+)$/;e&&o(t(e,","),function(e){var t=n.exec(e),r="~"===t[1],i=r?"span":"div",a=t[2];y[a]=y[i],R[a]=i,r||(S[a.toUpperCase()]={},S[a]={}),v[a]||(v[a]=v[i]),o(y,function(e){e[i]&&(e[a]=e[i])})})}function h(e){var n=/^([+\-]?)(\w+)\[([^\]]+)\]$/;e&&o(t(e,","),function(e){var r=n.exec(e),i,a;r&&(a=r[1],i=a?y[r[2]]:y[r[2]]={"#comment":{}},i=y[r[2]],o(t(r[3],"|"),function(e){"-"===a?delete i[e]:i[e]={}}))})}function m(e){var t=v[e],n;if(t)return t;for(n=b.length;n--;)if(t=b[n],t.pattern.test(e))return t}var g=this,v={},y={},b=[],C,x,w,_,N,E,S,k,T,R={},A={};e=e||{},x=n(e.schema),e.verify_html===!1&&(e.valid_elements="*[*]"),e.valid_styles&&(C={},o(e.valid_styles,function(e,t){C[t]=s(e)})),w=c("whitespace_elements","pre script noscript style textarea video audio iframe object"),_=c("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr"),N=c("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source wbr track"),E=c("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls"),k=c("non_empty_elements","td th iframe video audio object",N),T=c("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure"),S=c("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup",T),o((e.special||"script noscript style textarea").split(" "),function(e){A[e]=new RegExp("</"+e+"[^>]*>","gi")}),e.valid_elements?f(e.valid_elements):(o(x,function(e,t){v[t]={attributes:e.attributes,attributesOrder:e.attributesOrder},y[t]=e.children}),"html5"!=e.schema&&o(t("strong/b em/i"),function(e){e=t(e,"/"),v[e[1]].outputName=e[0]}),v.img.attributesDefault=[{name:"alt",value:""}],o(t("ol ul sub sup blockquote span font a table tbody tr strong em b i"),function(e){v[e]&&(v[e].removeEmpty=!0)}),o(t("p h1 h2 h3 h4 h5 h6 th td pre div address caption"),function(e){v[e].paddEmpty=!0}),o(t("span"),function(e){v[e].removeEmptyAttrs=!0})),p(e.custom_elements),h(e.valid_children),d(e.extended_valid_elements),h("+ol[ul|ol],+ul[ul|ol]"),e.invalid_elements&&o(s(e.invalid_elements),function(e){v[e]&&delete v[e]}),m("span")||d("span[!data-mce-type|*]"),g.children=y,g.styles=C,g.getBoolAttrs=function(){return E},g.getBlockElements=function(){return S},g.getTextBlockElements=function(){return T},g.getShortEndedElements=function(){return N},g.getSelfClosingElements=function(){return _},g.getNonEmptyElements=function(){return k},g.getWhiteSpaceElements=function(){return w},g.getSpecialElements=function(){return A},g.isValidChild=function(e,t){var n=y[e];return!(!n||!n[t])},g.isValid=function(e,t){var n,r,i=m(e);if(i){if(!t)return!0;if(i.attributes[t])return!0;if(n=i.attributePatterns)for(r=n.length;r--;)if(n[r].pattern.test(e))return!0}return!1},g.getElementRule=m,g.getCustomElements=function(){return R},g.addValidElements=d,g.setValidElements=f,g.addCustomElements=p,g.addValidChildren=h,g.elements=v}}),r(w,[x,m,p],function(e,t,n){var r=n.each;return function(n,i){var o=this,a=function(){};n=n||{},o.schema=i=i||new e,n.fix_self_closing!==!1&&(n.fix_self_closing=!0),r("comment cdata text start end pi doctype".split(" "),function(e){e&&(o[e]=n[e]||a)}),o.parse=function(e){function r(e){var t,n;for(t=d.length;t--&&d[t].name!==e;);if(t>=0){for(n=d.length-1;n>=t;n--)e=d[n],e.valid&&a.end(e.name);d.length=t}}function o(e,t,n,r,i){var o,a;if(t=t.toLowerCase(),n=t in b?t:I(n||r||i||""),x&&!g&&0!==t.indexOf("data-")){if(o=S[t],!o&&k){for(a=k.length;a--&&(o=k[a],!o.pattern.test(t)););-1===a&&(o=null)}if(!o)return;if(o.validValues&&!(n in o.validValues))return}f.map[t]=n,f.push({name:t,value:n})}var a=this,s,l=0,c,u,d=[],f,p,h,m,g,v,y,b,C,x,w,_,N,E,S,k,T,R,A,B,L,M,D,H,P,O=0,I=t.decode,F;for(M=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g"),D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g,y=i.getShortEndedElements(),L=n.self_closing_elements||i.getSelfClosingElements(),b=i.getBoolAttrs(),x=n.validate,v=n.remove_internals,F=n.fix_self_closing,H=i.getSpecialElements();s=M.exec(e);){if(l<s.index&&a.text(I(e.substr(l,s.index-l))),c=s[6])c=c.toLowerCase(),":"===c.charAt(0)&&(c=c.substr(1)),r(c);else if(c=s[7]){if(c=c.toLowerCase(),":"===c.charAt(0)&&(c=c.substr(1)),C=c in y,F&&L[c]&&d.length>0&&d[d.length-1].name===c&&r(c),!x||(w=i.getElementRule(c))){if(_=!0,x&&(S=w.attributes,k=w.attributePatterns),(E=s[8])?(g=-1!==E.indexOf("data-mce-type"),g&&v&&(_=!1),f=[],f.map={},E.replace(D,o)):(f=[],f.map={}),x&&!g){if(T=w.attributesRequired,R=w.attributesDefault,A=w.attributesForced,B=w.removeEmptyAttrs,B&&!f.length&&(_=!1),A)for(p=A.length;p--;)N=A[p],m=N.name,P=N.value,"{$uid}"===P&&(P="mce_"+O++),f.map[m]=P,f.push({name:m,value:P});if(R)for(p=R.length;p--;)N=R[p],m=N.name,m in f.map||(P=N.value,"{$uid}"===P&&(P="mce_"+O++),f.map[m]=P,f.push({name:m,value:P}));if(T){for(p=T.length;p--&&!(T[p]in f.map););-1===p&&(_=!1)}f.map["data-mce-bogus"]&&(_=!1)}_&&a.start(c,f,C)}else _=!1;if(u=H[c]){u.lastIndex=l=s.index+s[0].length,(s=u.exec(e))?(_&&(h=e.substr(l,s.index-l)),l=s.index+s[0].length):(h=e.substr(l),l=e.length),_&&(h.length>0&&a.text(h,!0),a.end(c)),M.lastIndex=l;continue}C||(E&&E.indexOf("/")==E.length-1?_&&a.end(c):d.push({name:c,valid:_}))}else(c=s[1])?a.comment(c):(c=s[2])?a.cdata(c):(c=s[3])?a.doctype(c):(c=s[4])&&a.pi(c,s[5]);l=s.index+s[0].length}for(l<e.length&&a.text(I(e.substr(l))),p=d.length-1;p>=0;p--)c=d[p],c.valid&&a.end(c.name)}}}),r(_,[C,x,w,p],function(e,t,n,r){var i=r.makeMap,o=r.each,a=r.explode,s=r.extend;return function(r,l){function c(t){var n,r,o,a,s,c,d,f,p,h,m,g,v,y;for(m=i("tr,td,th,tbody,thead,tfoot,table"),h=l.getNonEmptyElements(),g=l.getTextBlockElements(),n=0;n<t.length;n++)if(r=t[n],r.parent&&!r.fixed)if(g[r.name]&&"li"==r.parent.name){for(v=r.next;v&&g[v.name];)v.name="li",v.fixed=!0,r.parent.insert(v,r.parent),v=v.next;r.unwrap(r)}else{for(a=[r],o=r.parent;o&&!l.isValidChild(o.name,r.name)&&!m[o.name];o=o.parent)a.push(o);if(o&&a.length>1){for(a.reverse(),s=c=u.filterNode(a[0].clone()),p=0;p<a.length-1;p++){for(l.isValidChild(c.name,a[p].name)?(d=u.filterNode(a[p].clone()),c.append(d)):d=c,f=a[p].firstChild;f&&f!=a[p+1];)y=f.next,d.append(f),f=y;c=d}s.isEmpty(h)?o.insert(r,a[0],!0):(o.insert(s,a[0],!0),o.insert(r,s)),o=a[0],(o.isEmpty(h)||o.firstChild===o.lastChild&&"br"===o.firstChild.name)&&o.empty().remove()}else if(r.parent){if("li"===r.name){if(v=r.prev,v&&("ul"===v.name||"ul"===v.name)){v.append(r);continue}if(v=r.next,v&&("ul"===v.name||"ul"===v.name)){v.insert(r,v.firstChild,!0);continue}r.wrap(u.filterNode(new e("ul",1)));continue}l.isValidChild(r.parent.name,"div")&&l.isValidChild("div",r.name)?r.wrap(u.filterNode(new e("div",1))):"style"===r.name||"script"===r.name?r.empty().remove():r.unwrap()}}}var u=this,d={},f=[],p={},h={};r=r||{},r.validate="validate"in r?r.validate:!0,r.root_name=r.root_name||"body",u.schema=l=l||new t,u.filterNode=function(e){var t,n,r;n in d&&(r=p[n],r?r.push(e):p[n]=[e]),t=f.length;for(;t--;)n=f[t].name,n in e.attributes.map&&(r=h[n],r?r.push(e):h[n]=[e]);return e},u.addNodeFilter=function(e,t){o(a(e),function(e){var n=d[e];n||(d[e]=n=[]),n.push(t)})},u.addAttributeFilter=function(e,t){o(a(e),function(e){var n;for(n=0;n<f.length;n++)if(f[n].name===e)return f[n].callbacks.push(t),void 0;f.push({name:e,callbacks:[t]})})},u.parse=function(t,o){function a(){function e(e){e&&(t=e.firstChild,t&&3==t.type&&(t.value=t.value.replace(R,"")),t=e.lastChild,t&&3==t.type&&(t.value=t.value.replace(L,"")))}var t=y.firstChild,n,r;if(l.isValidChild(y.name,I.toLowerCase())){for(;t;)n=t.next,3==t.type||1==t.type&&"p"!==t.name&&!T[t.name]&&!t.attr("data-mce-type")?r?r.append(t):(r=u(I,1),y.insert(r,t),r.append(t)):(e(r),r=null),t=n;e(r)}}function u(t,n){var r=new e(t,n),i;return t in d&&(i=p[t],i?i.push(r):p[t]=[r]),r}function m(e){var t,n,r;for(t=e.prev;t&&3===t.type;)n=t.value.replace(L,""),n.length>0?(t.value=n,t=t.prev):(r=t.prev,t.remove(),t=r)}function g(e){var t,n={};for(t in e)"li"!==t&&"p"!=t&&(n[t]=e[t]);return n}var v,y,b,C,x,w,_,N,E,S,k,T,R,A=[],B,L,M,D,H,P,O,I;if(o=o||{},p={},h={},T=s(i("script,style,head,html,body,title,meta,param"),l.getBlockElements()),O=l.getNonEmptyElements(),P=l.children,k=r.validate,I="forced_root_block"in o?o.forced_root_block:r.forced_root_block,H=l.getWhiteSpaceElements(),R=/^[ \t\r\n]+/,L=/[ \t\r\n]+$/,M=/[ \t\r\n]+/g,D=/^[ \t\r\n]+$/,v=new n({validate:k,self_closing_elements:g(l.getSelfClosingElements()),cdata:function(e){b.append(u("#cdata",4)).value=e},text:function(e,t){var n;B||(e=e.replace(M," "),b.lastChild&&T[b.lastChild.name]&&(e=e.replace(R,""))),0!==e.length&&(n=u("#text",3),n.raw=!!t,b.append(n).value=e)},comment:function(e){b.append(u("#comment",8)).value=e},pi:function(e,t){b.append(u(e,7)).value=t,m(b)},doctype:function(e){var t;t=b.append(u("#doctype",10)),t.value=e,m(b)},start:function(e,t,n){var r,i,o,a,s;if(o=k?l.getElementRule(e):{}){for(r=u(o.outputName||e,1),r.attributes=t,r.shortEnded=n,b.append(r),s=P[b.name],s&&P[r.name]&&!s[r.name]&&A.push(r),i=f.length;i--;)a=f[i].name,a in t.map&&(E=h[a],E?E.push(r):h[a]=[r]);T[e]&&m(r),n||(b=r),!B&&H[e]&&(B=!0)}},end:function(t){var n,r,i,o,a;if(r=k?l.getElementRule(t):{}){if(T[t]&&!B){if(n=b.firstChild,n&&3===n.type)if(i=n.value.replace(R,""),i.length>0)n.value=i,n=n.next;else for(o=n.next,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.next,(0===i.length||D.test(i))&&(n.remove(),n=o),n=o;if(n=b.lastChild,n&&3===n.type)if(i=n.value.replace(L,""),i.length>0)n.value=i,n=n.prev;else for(o=n.prev,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.prev,(0===i.length||D.test(i))&&(n.remove(),n=o),n=o}if(B&&H[t]&&(B=!1),(r.removeEmpty||r.paddEmpty)&&b.isEmpty(O))if(r.paddEmpty)b.empty().append(new e("#text","3")).value="\xa0";else if(!b.attributes.map.name&&!b.attributes.map.id)return a=b.parent,b.empty().remove(),b=a,void 0;b=b.parent}}},l),y=b=new e(o.context||r.root_name,11),v.parse(t),k&&A.length&&(o.context?o.invalid=!0:c(A)),I&&("body"==y.name||o.isRootContent)&&a(),!o.invalid){for(S in p){for(E=d[S],C=p[S],_=C.length;_--;)C[_].parent||C.splice(_,1);for(x=0,w=E.length;w>x;x++)E[x](C,S,o)}for(x=0,w=f.length;w>x;x++)if(E=f[x],E.name in h){for(C=h[E.name],_=C.length;_--;)C[_].parent||C.splice(_,1);for(_=0,N=E.callbacks.length;N>_;_++)E.callbacks[_](C,E.name,o)}}return y},r.remove_trailing_brs&&u.addNodeFilter("br",function(t){var n,r=t.length,i,o=s({},l.getBlockElements()),a=l.getNonEmptyElements(),c,u,d,f,p,h;for(o.body=1,n=0;r>n;n++)if(i=t[n],c=i.parent,o[i.parent.name]&&i===c.lastChild){for(d=i.prev;d;){if(f=d.name,"span"!==f||"bookmark"!==d.attr("data-mce-type")){if("br"!==f)break;if("br"===f){i=null;break}}d=d.prev}i&&(i.remove(),c.isEmpty(a)&&(p=l.getElementRule(c.name),p&&(p.removeEmpty?c.remove():p.paddEmpty&&(c.empty().append(new e("#text",3)).value="\xa0"))))}else{for(u=i;c&&c.firstChild===u&&c.lastChild===u&&(u=c,!o[c.name]);)c=c.parent;u===c&&(h=new e("#text",3),h.value="\xa0",i.replace(h))}}),r.allow_html_in_named_anchor||u.addAttributeFilter("id,name",function(e){for(var t=e.length,n,r,i,o;t--;)if(o=e[t],"a"===o.name&&o.firstChild&&!o.attr("href")){i=o.parent,n=o.lastChild;do r=n.prev,i.insert(n,o),n=r;while(n)}})}}),r(N,[m,p],function(e,t){var n=t.makeMap;return function(t){var r=[],i,o,a,s,l;return t=t||{},i=t.indent,o=n(t.indent_before||""),a=n(t.indent_after||""),s=e.getEncodeFunc(t.entity_encoding||"raw",t.entities),l="html"==t.element_format,{start:function(e,t,n){var c,u,d,f;if(i&&o[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n")),r.push("<",e),t)for(c=0,u=t.length;u>c;c++)d=t[c],r.push(" ",d.name,'="',s(d.value,!0),'"');r[r.length]=!n||l?">":" />",n&&i&&a[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n"))},end:function(e){var t;r.push("</",e,">"),i&&a[e]&&r.length>0&&(t=r[r.length-1],t.length>0&&"\n"!==t&&r.push("\n"))},text:function(e,t){e.length>0&&(r[r.length]=t?e:s(e))},cdata:function(e){r.push("<![CDATA[",e,"]]>")},comment:function(e){r.push("<!--",e,"-->")},pi:function(e,t){t?r.push("<?",e," ",t,"?>"):r.push("<?",e,"?>"),i&&r.push("\n")},doctype:function(e){r.push("<!DOCTYPE",e,">",i?"\n":"")},reset:function(){r.length=0},getContent:function(){return r.join("").replace(/\n$/,"")}}}}),r(E,[N,x],function(e,t){return function(n,r){var i=this,o=new e(n);n=n||{},n.validate="validate"in n?n.validate:!0,i.schema=r=r||new t,i.writer=o,i.serialize=function(e){function t(e){var n=i[e.type],s,l,c,u,d,f,p,h,m;if(n)n(e);else{if(s=e.name,l=e.shortEnded,c=e.attributes,a&&c&&c.length>1){for(f=[],f.map={},m=r.getElementRule(e.name),p=0,h=m.attributesOrder.length;h>p;p++)u=m.attributesOrder[p],u in c.map&&(d=c.map[u],f.map[u]=d,f.push({name:u,value:d}));for(p=0,h=c.length;h>p;p++)u=c[p].name,u in f.map||(d=c.map[u],f.map[u]=d,f.push({name:u,value:d}));c=f}if(o.start(e.name,c,l),!l){if(e=e.firstChild)do t(e);while(e=e.next);o.end(s)}}}var i,a;return a=n.validate,i={3:function(e){o.text(e.value,e.raw)},8:function(e){o.comment(e.value)},7:function(e){o.pi(e.name,e.value)},10:function(e){o.doctype(e.value)},4:function(e){o.cdata(e.value)},11:function(e){if(e=e.firstChild)do t(e);while(e=e.next)}},o.reset(),1!=e.type||n.inner?i[11](e):t(e),o.getContent()}}}),r(S,[v,_,m,E,C,x,g,p],function(e,t,n,r,i,o,a,s){var l=s.each,c=s.trim,u=e.DOM;return function(e,i){var s,d,f;return i&&(s=i.dom,d=i.schema),s=s||u,d=d||new o(e),e.entity_encoding=e.entity_encoding||"named",e.remove_trailing_brs="remove_trailing_brs"in e?e.remove_trailing_brs:!0,f=new t(e,d),f.addAttributeFilter("src,href,style",function(t,n){for(var r=t.length,i,o,a="data-mce-"+n,l=e.url_converter,c=e.url_converter_scope,u;r--;)i=t[r],o=i.attributes.map[a],o!==u?(i.attr(n,o.length>0?o:null),i.attr(a,null)):(o=i.attributes.map[n],"style"===n?o=s.serializeStyle(s.parseStyle(o),i.name):l&&(o=l.call(c,o,n,i.name)),i.attr(n,o.length>0?o:null))}),f.addAttributeFilter("class",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.attr("class").replace(/(?:^|\s)mce-item-\w+(?!\S)/g,""),n.attr("class",r.length>0?r:null)}),f.addAttributeFilter("data-mce-type",function(e,t,n){for(var r=e.length,i;r--;)i=e[r],"bookmark"!==i.attributes.map["data-mce-type"]||n.cleanup||i.remove()}),f.addAttributeFilter("data-mce-expando",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),f.addNodeFilter("noscript",function(e){for(var t=e.length,r;t--;)r=e[t].firstChild,r&&(r.value=n.decode(r.value))}),f.addNodeFilter("script,style",function(e,t){function n(e){return e.replace(/(<!--\[CDATA\[|\]\]-->)/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi,"").replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}for(var r=e.length,i,o;r--;)i=e[r],o=i.firstChild?i.firstChild.value:"","script"===t?(i.attr("type",(i.attr("type")||"text/javascript").replace(/^mce\-/,"")),o.length>0&&(i.firstChild.value="// <![CDATA[\n"+n(o)+"\n// ]]>")):o.length>0&&(i.firstChild.value="<!--\n"+n(o)+"\n-->")}),f.addNodeFilter("#comment",function(e){for(var t=e.length,n;t--;)n=e[t],0===n.value.indexOf("[CDATA[")?(n.name="#cdata",n.type=4,n.value=n.value.replace(/^\[CDATA\[|\]\]$/g,"")):0===n.value.indexOf("mce:protected ")&&(n.name="#text",n.type=3,n.raw=!0,n.value=unescape(n.value).substr(14))}),f.addNodeFilter("xml:namespace,input",function(e,t){for(var n=e.length,r;n--;)r=e[n],7===r.type?r.remove():1===r.type&&("input"!==t||"type"in r.attributes.map||r.attr("type","text"))}),e.fix_list_elements&&f.addNodeFilter("ul,ol",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.parent,("ul"===r.name||"ol"===r.name)&&n.prev&&"li"===n.prev.name&&n.prev.append(n)}),f.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style,data-mce-selected",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),{schema:d,addNodeFilter:f.addNodeFilter,addAttributeFilter:f.addAttributeFilter,serialize:function(t,n){var i=this,o,u,p,h,m;return a.ie&&s.select("script,style,select,map").length>0?(m=t.innerHTML,t=t.cloneNode(!1),s.setHTML(t,m)):t=t.cloneNode(!0),o=t.ownerDocument.implementation,o.createHTMLDocument&&(u=o.createHTMLDocument(""),l("BODY"==t.nodeName?t.childNodes:[t],function(e){u.body.appendChild(u.importNode(e,!0))}),t="BODY"!=t.nodeName?u.body.firstChild:u.body,p=s.doc,s.doc=u),n=n||{},n.format=n.format||"html",n.selection&&(n.forced_root_block=""),n.no_events||(n.node=t,i.onPreProcess(n)),h=new r(e,d),n.content=h.serialize(f.parse(c(n.getInner?t.innerHTML:s.getOuterHTML(t)),n)),n.cleanup||(n.content=n.content.replace(/\uFEFF/g,"")),n.no_events||i.onPostProcess(n),p&&(s.doc=p),n.node=null,n.content},addRules:function(e){d.addValidElements(e)},setRules:function(e){d.setValidElements(e)},onPreProcess:function(e){i&&i.fire("PreProcess",e)},onPostProcess:function(e){i&&i.fire("PostProcess",e)}}}}),r(k,[],function(){function e(e){function t(t,n){var r,i=0,o,a,s,l,c,u,d=-1,f;if(r=t.duplicate(),r.collapse(n),f=r.parentElement(),f.ownerDocument===e.dom.doc){for(;"false"===f.contentEditable;)f=f.parentNode;if(!f.hasChildNodes())return{node:f,inside:1};for(s=f.children,o=s.length-1;o>=i;)if(u=Math.floor((i+o)/2),l=s[u],r.moveToElementText(l),d=r.compareEndPoints(n?"StartToStart":"EndToEnd",t),d>0)o=u-1;else{if(!(0>d))return{node:l};i=u+1}if(0>d)for(l?r.collapse(!1):(r.moveToElementText(f),r.collapse(!0),l=f,a=!0),c=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",1)&&f==r.parentElement();)c++;else for(r.collapse(!0),c=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",-1)&&f==r.parentElement();)c++;return{node:l,position:d,offset:c,inside:a}}}function n(){function n(e){var n=t(o,e),r,i,s=0,l,c,u;if(r=n.node,i=n.offset,n.inside&&!r.hasChildNodes())return a[e?"setStart":"setEnd"](r,0),void 0;if(i===c)return a[e?"setStartBefore":"setEndAfter"](r),void 0;if(n.position<0){if(l=n.inside?r.firstChild:r.nextSibling,!l)return a[e?"setStartAfter":"setEndAfter"](r),void 0;if(!i)return 3==l.nodeType?a[e?"setStart":"setEnd"](l,0):a[e?"setStartBefore":"setEndBefore"](l),void 0;for(;l;){if(u=l.nodeValue,s+=u.length,s>=i){r=l,s-=i,s=u.length-s;break}l=l.nextSibling}}else{if(l=r.previousSibling,!l)return a[e?"setStartBefore":"setEndBefore"](r);if(!i)return 3==r.nodeType?a[e?"setStart":"setEnd"](l,r.nodeValue.length):a[e?"setStartAfter":"setEndAfter"](l),void 0;for(;l;){if(s+=l.nodeValue.length,s>=i){r=l,s-=i;break}l=l.previousSibling}}a[e?"setStart":"setEnd"](r,s)}var o=e.getRng(),a=i.createRng(),s,l,c,u,d;if(s=o.item?o.item(0):o.parentElement(),s.ownerDocument!=i.doc)return a;if(l=e.isCollapsed(),o.item)return a.setStart(s.parentNode,i.nodeIndex(s)),a.setEnd(a.startContainer,a.startOffset+1),a;try{n(!0),l||n()}catch(f){if(-2147024809!=f.number)throw f;d=r.getBookmark(2),c=o.duplicate(),c.collapse(!0),s=c.parentElement(),l||(c=o.duplicate(),c.collapse(!1),u=c.parentElement(),u.innerHTML=u.innerHTML),s.innerHTML=s.innerHTML,r.moveToBookmark(d),o=e.getRng(),n(!0),l||n()}return a}var r=this,i=e.dom,o=!1;this.getBookmark=function(n){function r(e){var t,n,r,o,a=[];for(t=e.parentNode,n=i.getRoot().parentNode;t!=n&&9!==t.nodeType;){for(r=t.children,o=r.length;o--;)if(e===r[o]){a.push(o);break}e=t,t=t.parentNode}return a}function o(e){var n;return n=t(a,e),n?{position:n.position,offset:n.offset,indexes:r(n.node),inside:n.inside}:void 0}var a=e.getRng(),s={};return 2===n&&(a.item?s.start={ctrl:!0,indexes:r(a.item(0))}:(s.start=o(!0),e.isCollapsed()||(s.end=o()))),s},this.moveToBookmark=function(e){function t(e){var t,n,r,o;for(t=i.getRoot(),n=e.length-1;n>=0;n--)o=t.children,r=e[n],r<=o.length-1&&(t=o[r]);return t}function n(n){var i=e[n?"start":"end"],a,s,l,c;i&&(a=i.position>0,s=o.createTextRange(),s.moveToElementText(t(i.indexes)),c=i.offset,c!==l?(s.collapse(i.inside||a),s.moveStart("character",a?-c:c)):s.collapse(n),r.setEndPoint(n?"StartToStart":"EndToStart",s),n&&r.collapse(!0)) +}var r,o=i.doc.body;e.start&&(e.start.ctrl?(r=o.createControlRange(),r.addElement(t(e.start.indexes)),r.select()):(r=o.createTextRange(),n(!0),n(),r.select()))},this.addRange=function(t){function n(e){var t,n,a,d,h;a=i.create("a"),t=e?s:c,n=e?l:u,d=r.duplicate(),(t==f||t==f.documentElement)&&(t=p,n=0),3==t.nodeType?(t.parentNode.insertBefore(a,t),d.moveToElementText(a),d.moveStart("character",n),i.remove(a),r.setEndPoint(e?"StartToStart":"EndToEnd",d)):(h=t.childNodes,h.length?(n>=h.length?i.insertAfter(a,h[h.length-1]):t.insertBefore(a,h[n]),d.moveToElementText(a)):t.canHaveHTML&&(t.innerHTML="<span></span>",a=t.firstChild,d.moveToElementText(a),d.collapse(o)),r.setEndPoint(e?"StartToStart":"EndToEnd",d),i.remove(a))}var r,a,s,l,c,u,d,f=e.dom.doc,p=f.body,h,m;if(s=t.startContainer,l=t.startOffset,c=t.endContainer,u=t.endOffset,r=p.createTextRange(),s==c&&1==s.nodeType){if(l==u&&!s.hasChildNodes()){if(s.canHaveHTML)return d=s.previousSibling,d&&!d.hasChildNodes()&&i.isBlock(d)?d.innerHTML="":d=null,s.innerHTML="<span></span><span></span>",r.moveToElementText(s.lastChild),r.select(),i.doc.selection.clear(),s.innerHTML="",d&&(d.innerHTML=""),void 0;l=i.nodeIndex(s),s=s.parentNode}if(l==u-1)try{if(m=s.childNodes[l],a=p.createControlRange(),a.addElement(m),a.select(),h=e.getRng(),h.item&&m===h.item(0))return}catch(g){}}n(!0),n(),r.select()},this.getRangeAt=n}return e}),r(T,[g],function(e){return{BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(e){return e.shiftKey||e.ctrlKey||e.altKey},metaKeyPressed:function(t){return(e.mac?t.ctrlKey||t.metaKey:t.ctrlKey)&&!t.altKey}}}),r(R,[T,p,g],function(e,t,n){return function(r,i){function o(e){return i.settings.object_resizing===!1?!1:/TABLE|IMG|DIV/.test(e.nodeName)?"false"===e.getAttribute("data-mce-resize")?!1:!0:!1}function a(t){var n,r;n=t.screenX-E,r=t.screenY-S,M=n*N[2]+R,D=r*N[3]+A,M=5>M?5:M,D=5>D?5:D,(e.modifierPressed(t)||"IMG"==x.nodeName&&0!==N[2]*N[3])&&(M=Math.round(D/B),D=Math.round(M*B)),b.setStyles(w,{width:M,height:D}),N[2]<0&&w.clientWidth<=M&&b.setStyle(w,"left",k+(R-M)),N[3]<0&&w.clientHeight<=D&&b.setStyle(w,"top",T+(A-D)),L||(i.fire("ObjectResizeStart",{target:x,width:R,height:A}),L=!0)}function s(){function e(e,t){t&&(x.style[e]||!i.schema.isValid(x.nodeName.toLowerCase(),e)?b.setStyle(x,e,t):b.setAttrib(x,e,t))}L=!1,e("width",M),e("height",D),b.unbind(H,"mousemove",a),b.unbind(H,"mouseup",s),P!=H&&(b.unbind(P,"mousemove",a),b.unbind(P,"mouseup",s)),b.remove(w),O&&"TABLE"!=x.nodeName||l(x),i.fire("ObjectResized",{target:x,width:M,height:D}),i.nodeChanged()}function l(e,t,n){var r,l,u,d,f;r=b.getPos(e,i.getBody()),k=r.x,T=r.y,f=e.getBoundingClientRect(),l=f.width||f.right-f.left,u=f.height||f.bottom-f.top,x!=e&&(m(),x=e,M=D=0),d=i.fire("ObjectSelected",{target:e}),o(e)&&!d.isDefaultPrevented()?C(_,function(e,r){function o(t){L=!0,E=t.screenX,S=t.screenY,R=x.clientWidth,A=x.clientHeight,B=A/R,N=e,w=x.cloneNode(!0),b.addClass(w,"mce-clonedresizable"),w.contentEditable=!1,w.unSelectabe=!0,b.setStyles(w,{left:k,top:T,margin:0}),w.removeAttribute("data-mce-selected"),i.getBody().appendChild(w),b.bind(H,"mousemove",a),b.bind(H,"mouseup",s),P!=H&&(b.bind(P,"mousemove",a),b.bind(P,"mouseup",s))}var c,d;return t?(r==t&&o(n),void 0):(c=b.get("mceResizeHandle"+r),c?b.show(c):(d=i.getBody(),c=b.add(d,"div",{id:"mceResizeHandle"+r,"data-mce-bogus":!0,"class":"mce-resizehandle",contentEditable:!1,unSelectabe:!0,style:"cursor:"+r+"-resize; margin:0; padding:0"}),b.bind(c,"mousedown",function(e){e.preventDefault(),o(e)})),b.setStyles(c,{left:l*e[0]+k-c.offsetWidth/2,top:u*e[1]+T-c.offsetHeight/2}),void 0)}):c(),x.setAttribute("data-mce-selected","1")}function c(){var e,t;x&&x.removeAttribute("data-mce-selected");for(e in _)t=b.get("mceResizeHandle"+e),t&&(b.unbind(t),b.remove(t))}function u(e){function t(e,t){do if(e===t)return!0;while(e=e.parentNode)}var n;return C(b.select("img[data-mce-selected],hr[data-mce-selected]"),function(e){e.removeAttribute("data-mce-selected")}),n="mousedown"==e.type?e.target:r.getNode(),n=b.getParent(n,O?"table":"table,img,hr"),n&&(g(),t(r.getStart(),n)&&t(r.getEnd(),n)&&(!O||n!=r.getStart()&&"IMG"!==r.getStart().nodeName))?(l(n),void 0):(c(),void 0)}function d(e,t,n){e&&e.attachEvent&&e.attachEvent("on"+t,n)}function f(e,t,n){e&&e.detachEvent&&e.detachEvent("on"+t,n)}function p(e){var t=e.srcElement,n,r,o,a,s,c,u;n=t.getBoundingClientRect(),c=I.clientX-n.left,u=I.clientY-n.top;for(r in _)if(o=_[r],a=t.offsetWidth*o[0],s=t.offsetHeight*o[1],Math.abs(a-c)<8&&Math.abs(s-u)<8){N=o;break}L=!0,i.getDoc().selection.empty(),l(t,r,I)}function h(e){var t=e.srcElement;if(t!=x){if(m(),0===t.id.indexOf("mceResizeHandle"))return e.returnValue=!1,void 0;("IMG"==t.nodeName||"TABLE"==t.nodeName)&&(c(),x=t,d(t,"resizestart",p))}}function m(){f(x,"resizestart",p)}function g(){try{i.getDoc().execCommand("enableObjectResizing",!1,!1)}catch(e){}}function v(e){var t;if(O){t=H.body.createControlRange();try{return t.addElement(e),t.select(),!0}catch(n){}}}function y(){x=w=null,O&&(m(),f(i.getBody(),"controlselect",h))}var b=i.dom,C=t.each,x,w,_,N,E,S,k,T,R,A,B,L,M,D,H=i.getDoc(),P=document,O=n.ie,I;_={n:[.5,0,0,-1],e:[1,.5,1,0],s:[.5,1,0,1],w:[0,.5,-1,0],nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};var F=".mce-content-body";return i.contentStyles.push(F+" div.mce-resizehandle {"+"position: absolute;"+"border: 1px solid black;"+"background: #FFF;"+"width: 5px;"+"height: 5px;"+"z-index: 10000"+"}"+F+" .mce-resizehandle:hover {"+"background: #000"+"}"+F+" img[data-mce-selected], hr[data-mce-selected] {"+"outline: 1px solid black;"+"resize: none"+"}"+F+" .mce-clonedresizable {"+"position: absolute;"+(n.gecko?"":"outline: 1px dashed black;")+"opacity: .5;"+"filter: alpha(opacity=50);"+"z-index: 10000"+"}"),i.on("init",function(){O?(i.on("ObjectResized",function(e){"TABLE"!=e.target.nodeName&&(c(),v(e.target))}),d(i.getBody(),"controlselect",h),i.on("mousedown",function(e){I=e})):g(),i.on("nodechange mousedown ResizeEditor",u),i.on("keydown keyup",function(e){x&&"TABLE"==x.nodeName&&u(e)})}),{controlSelect:v,destroy:y}}}),r(A,[f,k,R,g,p],function(e,n,r,i,o){function a(e,t,i,o){var a=this;a.dom=e,a.win=t,a.serializer=i,a.editor=o,a.controlSelection=new r(a,o),a.win.getSelection||(a.tridentSel=new n(a))}var s=o.each,l=o.grep,c=o.trim,u=i.ie,d=i.opera;return a.prototype={setCursorLocation:function(e,t){var n=this,r=n.dom.createRng();r.setStart(e,t),r.setEnd(e,t),n.setRng(r),n.collapse(!1)},getContent:function(e){var n=this,r=n.getRng(),i=n.dom.create("body"),o=n.getSel(),a,s,l;return e=e||{},a=s="",e.get=!0,e.format=e.format||"html",e.selection=!0,n.editor.fire("BeforeGetContent",e),"text"==e.format?n.isCollapsed()?"":r.text||(o.toString?o.toString():""):(r.cloneContents?(l=r.cloneContents(),l&&i.appendChild(l)):r.item!==t||r.htmlText!==t?(i.innerHTML="<br>"+(r.item?r.item(0).outerHTML:r.htmlText),i.removeChild(i.firstChild)):i.innerHTML=r.toString(),/^\s/.test(i.innerHTML)&&(a=" "),/\s+$/.test(i.innerHTML)&&(s=" "),e.getInner=!0,e.content=n.isCollapsed()?"":a+n.serializer.serialize(i,e)+s,n.editor.fire("GetContent",e),e.content)},setContent:function(e,t){var n=this,r=n.getRng(),i,o=n.win.document,a,s;if(t=t||{format:"html"},t.set=!0,t.selection=!0,e=t.content=e,t.no_events||n.editor.fire("BeforeSetContent",t),e=t.content,r.insertNode){e+='<span id="__caret">_</span>',r.startContainer==o&&r.endContainer==o?o.body.innerHTML=e:(r.deleteContents(),0===o.body.childNodes.length?o.body.innerHTML=e:r.createContextualFragment?r.insertNode(r.createContextualFragment(e)):(a=o.createDocumentFragment(),s=o.createElement("div"),a.appendChild(s),s.outerHTML=e,r.insertNode(a))),i=n.dom.get("__caret"),r=o.createRange(),r.setStartBefore(i),r.setEndBefore(i),n.setRng(r),n.dom.remove("__caret");try{n.setRng(r)}catch(l){}}else r.item&&(o.execCommand("Delete",!1,null),r=n.getRng()),/^\s+/.test(e)?(r.pasteHTML('<span id="__mce_tmp">_</span>'+e),n.dom.remove("__mce_tmp")):r.pasteHTML(e);t.no_events||n.editor.fire("SetContent",t)},getStart:function(){var e=this,t=e.getRng(),n,r,i,o;if(t.duplicate||t.item){if(t.item)return t.item(0);for(i=t.duplicate(),i.collapse(1),n=i.parentElement(),n.ownerDocument!==e.dom.doc&&(n=e.dom.getRoot()),r=o=t.parentElement();o=o.parentNode;)if(o==n){n=r;break}return n}return n=t.startContainer,1==n.nodeType&&n.hasChildNodes()&&(n=n.childNodes[Math.min(n.childNodes.length-1,t.startOffset)]),n&&3==n.nodeType?n.parentNode:n},getEnd:function(){var e=this,t=e.getRng(),n,r;return t.duplicate||t.item?t.item?t.item(0):(t=t.duplicate(),t.collapse(0),n=t.parentElement(),n.ownerDocument!==e.dom.doc&&(n=e.dom.getRoot()),n&&"BODY"==n.nodeName?n.lastChild||n:n):(n=t.endContainer,r=t.endOffset,1==n.nodeType&&n.hasChildNodes()&&(n=n.childNodes[r>0?r-1:r]),n&&3==n.nodeType?n.parentNode:n)},getBookmark:function(e,t){function n(e,t){var n=0;return s(a.select(e),function(e,r){e==t&&(n=r)}),n}function r(e){function t(t){var n,r,i,o=t?"start":"end";n=e[o+"Container"],r=e[o+"Offset"],1==n.nodeType&&"TR"==n.nodeName&&(i=n.childNodes,n=i[Math.min(t?r:r-1,i.length-1)],n&&(r=t?0:n.childNodes.length,e["set"+(t?"Start":"End")](n,r)))}return t(!0),t(),e}function i(){function e(e,n){var i=e[n?"startContainer":"endContainer"],a=e[n?"startOffset":"endOffset"],s=[],l,c,u=0;if(3==i.nodeType){if(t)for(l=i.previousSibling;l&&3==l.nodeType;l=l.previousSibling)a+=l.nodeValue.length;s.push(a)}else c=i.childNodes,a>=c.length&&c.length&&(u=1,a=Math.max(0,c.length-1)),s.push(o.dom.nodeIndex(c[a],t)+u);for(;i&&i!=r;i=i.parentNode)s.push(o.dom.nodeIndex(i,t));return s}var n=o.getRng(!0),r=a.getRoot(),i={};return i.start=e(n,!0),o.isCollapsed()||(i.end=e(n)),i}var o=this,a=o.dom,l,c,u,d,f,p,h="",m;if(2==e)return p=o.getNode(),f=p.nodeName,"IMG"==f?{name:f,index:n(f,p)}:o.tridentSel?o.tridentSel.getBookmark(e):i();if(e)return{rng:o.getRng()};if(l=o.getRng(),u=a.uniqueId(),d=o.isCollapsed(),m="overflow:hidden;line-height:0px",l.duplicate||l.item){if(l.item)return p=l.item(0),f=p.nodeName,{name:f,index:n(f,p)};c=l.duplicate();try{l.collapse(),l.pasteHTML('<span data-mce-type="bookmark" id="'+u+'_start" style="'+m+'">'+h+"</span>"),d||(c.collapse(!1),l.moveToElementText(c.parentElement()),0===l.compareEndPoints("StartToEnd",c)&&c.move("character",-1),c.pasteHTML('<span data-mce-type="bookmark" id="'+u+'_end" style="'+m+'">'+h+"</span>"))}catch(g){return null}}else{if(p=o.getNode(),f=p.nodeName,"IMG"==f)return{name:f,index:n(f,p)};c=r(l.cloneRange()),d||(c.collapse(!1),c.insertNode(a.create("span",{"data-mce-type":"bookmark",id:u+"_end",style:m},h))),l=r(l),l.collapse(!0),l.insertNode(a.create("span",{"data-mce-type":"bookmark",id:u+"_start",style:m},h))}return o.moveToBookmark({id:u,keep:1}),{id:u}},moveToBookmark:function(e){function t(t){var n=e[t?"start":"end"],r,i,o,s;if(n){for(o=n[0],i=c,r=n.length-1;r>=1;r--){if(s=i.childNodes,n[r]>s.length-1)return;i=s[n[r]]}3===i.nodeType&&(o=Math.min(n[0],i.nodeValue.length)),1===i.nodeType&&(o=Math.min(n[0],i.childNodes.length)),t?a.setStart(i,o):a.setEnd(i,o)}return!0}function n(t){var n=o.get(e.id+"_"+t),r,i,a,c,u=e.keep;if(n&&(r=n.parentNode,"start"==t?(u?(r=n.firstChild,i=1):i=o.nodeIndex(n),f=p=r,h=m=i):(u?(r=n.firstChild,i=1):i=o.nodeIndex(n),p=r,m=i),!u)){for(c=n.previousSibling,a=n.nextSibling,s(l(n.childNodes),function(e){3==e.nodeType&&(e.nodeValue=e.nodeValue.replace(/\uFEFF/g,""))});n=o.get(e.id+"_"+t);)o.remove(n,1);c&&a&&c.nodeType==a.nodeType&&3==c.nodeType&&!d&&(i=c.nodeValue.length,c.appendData(a.nodeValue),o.remove(a),"start"==t?(f=p=c,h=m=i):(p=c,m=i))}}function r(e){return!o.isBlock(e)||e.innerHTML||u||(e.innerHTML='<br data-mce-bogus="1" />'),e}var i=this,o=i.dom,a,c,f,p,h,m;if(e)if(e.start){if(a=o.createRng(),c=o.getRoot(),i.tridentSel)return i.tridentSel.moveToBookmark(e);t(!0)&&t()&&i.setRng(a)}else e.id?(n("start"),n("end"),f&&(a=o.createRng(),a.setStart(r(f),h),a.setEnd(r(p),m),i.setRng(a))):e.name?i.select(o.select(e.name)[e.index]):e.rng&&i.setRng(e.rng)},select:function(t,n){function r(t,n){var r=new e(t,t);do{if(3==t.nodeType&&0!==c(t.nodeValue).length)return n?a.setStart(t,0):a.setEnd(t,t.nodeValue.length),void 0;if("BR"==t.nodeName)return n?a.setStartBefore(t):a.setEndBefore(t),void 0}while(t=n?r.next():r.prev())}var i=this,o=i.dom,a=o.createRng(),s;if(t){if(!n&&i.controlSelection.controlSelect(t))return;s=o.nodeIndex(t),a.setStart(t.parentNode,s),a.setEnd(t.parentNode,s+1),n&&(r(t,1),r(t)),i.setRng(a)}return t},isCollapsed:function(){var e=this,t=e.getRng(),n=e.getSel();return!t||t.item?!1:t.compareEndPoints?0===t.compareEndPoints("StartToEnd",t):!n||t.collapsed},collapse:function(e){var t=this,n=t.getRng(),r;n.item&&(r=n.item(0),n=t.win.document.body.createTextRange(),n.moveToElementText(r)),n.collapse(!!e),t.setRng(n)},getSel:function(){var e=this.win;return e.getSelection?e.getSelection():e.document.selection},getRng:function(e){var t=this,n,r,i,o=t.win.document,a;if(!e&&t.restoreRng)return t.restoreRng;if(e&&t.tridentSel)return t.tridentSel.getRangeAt(0);try{(n=t.getSel())&&(r=n.rangeCount>0?n.getRangeAt(0):n.createRange?n.createRange():o.createRange())}catch(s){}if(u&&r&&r.setStart){try{a=o.selection.createRange()}catch(s){}a&&a.item&&(i=a.item(0),r=o.createRange(),r.setStartBefore(i),r.setEndAfter(i))}return r||(r=o.createRange?o.createRange():o.body.createTextRange()),r.setStart&&9===r.startContainer.nodeType&&r.collapsed&&(i=t.dom.getRoot(),r.setStart(i,0),r.setEnd(i,0)),t.selectedRange&&t.explicitRange&&(0===r.compareBoundaryPoints(r.START_TO_START,t.selectedRange)&&0===r.compareBoundaryPoints(r.END_TO_END,t.selectedRange)?r=t.explicitRange:(t.selectedRange=null,t.explicitRange=null)),r},setRng:function(e,t){var n=this,r;if(e.select)try{e.select()}catch(i){}else if(n.tridentSel){if(e.cloneRange)try{return n.tridentSel.addRange(e),void 0}catch(i){}}else if(r=n.getSel()){n.explicitRange=e;try{r.removeAllRanges()}catch(i){}r.addRange(e),t===!1&&r.extend&&(r.collapse(e.endContainer,e.endOffset),r.extend(e.startContainer,e.startOffset)),n.selectedRange=r.rangeCount>0?r.getRangeAt(0):null}},setNode:function(e){var t=this;return t.setContent(t.dom.getOuterHTML(e)),e},getNode:function(){function e(e,t){for(var n=e;e&&3===e.nodeType&&0===e.length;)e=t?e.nextSibling:e.previousSibling;return e||n}var t=this,n=t.getRng(),r,i=n.startContainer,o=n.endContainer,a=n.startOffset,s=n.endOffset;return n?n.setStart?(r=n.commonAncestorContainer,!n.collapsed&&(i==o&&2>s-a&&i.hasChildNodes()&&(r=i.childNodes[a]),3===i.nodeType&&3===o.nodeType&&(i=i.length===a?e(i.nextSibling,!0):i.parentNode,o=0===s?e(o.previousSibling,!1):o.parentNode,i&&i===o))?i:r&&3==r.nodeType?r.parentNode:r):n.item?n.item(0):n.parentElement():t.dom.getRoot()},getSelectedBlocks:function(t,n){var r=this,i=r.dom,o,a,s=[];if(a=i.getRoot(),t=i.getParent(t||r.getStart(),i.isBlock),n=i.getParent(n||r.getEnd(),i.isBlock),t&&t!=a&&s.push(t),t&&n&&t!=n){o=t;for(var l=new e(t,a);(o=l.next())&&o!=n;)i.isBlock(o)&&s.push(o)}return n&&t!=n&&n!=a&&s.push(n),s},isForward:function(){var e=this.dom,t=this.getSel(),n,r;return t&&t.anchorNode&&t.focusNode?(n=e.createRng(),n.setStart(t.anchorNode,t.anchorOffset),n.collapse(!0),r=e.createRng(),r.setStart(t.focusNode,t.focusOffset),r.collapse(!0),n.compareBoundaryPoints(n.START_TO_START,r)<=0):!0},normalize:function(){function t(t){function a(t,n){for(var r=new e(t,f.getParent(t.parentNode,f.isBlock)||p);t=r[n?"prev":"next"]();)if("BR"===t.nodeName)return!0}function s(e,t){return e.previousSibling&&e.previousSibling.nodeName==t}function l(t,n){var r,a;for(n=n||c,r=new e(n,f.getParent(n.parentNode,f.isBlock)||p);h=r[t?"prev":"next"]();){if(3===h.nodeType&&h.nodeValue.length>0)return c=h,u=t?h.nodeValue.length:0,i=!0,void 0;if(f.isBlock(h)||m[h.nodeName.toLowerCase()])return;a=h}o&&a&&(c=a,i=!0,u=0)}var c,u,d,f=n.dom,p=f.getRoot(),h,m,g;if(c=r[(t?"start":"end")+"Container"],u=r[(t?"start":"end")+"Offset"],m=f.schema.getNonEmptyElements(),9===c.nodeType&&(c=f.getRoot(),u=0),c===p){if(t&&(h=c.childNodes[u>0?u-1:0],h&&(g=h.nodeName.toLowerCase(),m[h.nodeName]||"TABLE"==h.nodeName)))return;if(c.hasChildNodes()&&(u=Math.min(!t&&u>0?u-1:u,c.childNodes.length-1),c=c.childNodes[u],u=0,c.hasChildNodes()&&!/TABLE/.test(c.nodeName))){h=c,d=new e(c,p);do{if(3===h.nodeType&&h.nodeValue.length>0){u=t?0:h.nodeValue.length,c=h,i=!0;break}if(m[h.nodeName.toLowerCase()]){u=f.nodeIndex(h),c=h.parentNode,"IMG"!=h.nodeName||t||u++,i=!0;break}}while(h=t?d.next():d.prev())}}o&&(3===c.nodeType&&0===u&&l(!0),1===c.nodeType&&(h=c.childNodes[u],!h||"BR"!==h.nodeName||s(h,"A")||a(h)||a(h,!0)||l(!0,c.childNodes[u]))),t&&!o&&3===c.nodeType&&u===c.nodeValue.length&&l(!1),i&&r["set"+(t?"Start":"End")](c,u)}var n=this,r,i,o;u||(r=n.getRng(),o=r.collapsed,t(!0),o||t(),i&&(o&&r.collapse(!0),n.setRng(r,n.isForward())))},selectorChanged:function(e,t){var n=this,r;return n.selectorChangedData||(n.selectorChangedData={},r={},n.editor.on("NodeChange",function(e){var t=e.element,i=n.dom,o=i.getParents(t,null,i.getRoot()),a={};s(n.selectorChangedData,function(e,t){s(o,function(n){return i.is(n,t)?(r[t]||(s(e,function(e){e(!0,{node:n,selector:t,parents:o})}),r[t]=e),a[t]=e,!1):void 0})}),s(r,function(e,n){a[n]||(delete r[n],s(e,function(e){e(!1,{node:t,selector:n,parents:o})}))})})),n.selectorChangedData[e]||(n.selectorChangedData[e]=[]),n.selectorChangedData[e].push(t),n},scrollIntoView:function(e){var t,n,r=this,i=r.dom;n=i.getViewPort(r.editor.getWin()),t=i.getPos(e).y,(t<n.y||t+25>n.y+n.h)&&r.editor.getWin().scrollTo(0,t<n.y?t:t-n.h+25)},destroy:function(){this.win=null,this.controlSelection.destroy()}},a}),r(B,[p],function(e){function t(e){this.walk=function(t,r){function i(e){var t;return t=e[0],3===t.nodeType&&t===l&&c>=t.nodeValue.length&&e.splice(0,1),t=e[e.length-1],0===d&&e.length>0&&t===u&&3===t.nodeType&&e.splice(e.length-1,1),e}function o(e,t,n){for(var r=[];e&&e!=n;e=e[t])r.push(e);return r}function a(e,t){do{if(e.parentNode==t)return e;e=e.parentNode}while(e)}function s(e,t,n){var a=n?"nextSibling":"previousSibling";for(m=e,g=m.parentNode;m&&m!=t;m=g)g=m.parentNode,v=o(m==e?m:m[a],a),v.length&&(n||v.reverse(),r(i(v)))}var l=t.startContainer,c=t.startOffset,u=t.endContainer,d=t.endOffset,f,p,h,m,g,v,y;if(y=e.select("td.mce-item-selected,th.mce-item-selected"),y.length>0)return n(y,function(e){r([e])}),void 0;if(1==l.nodeType&&l.hasChildNodes()&&(l=l.childNodes[c]),1==u.nodeType&&u.hasChildNodes()&&(u=u.childNodes[Math.min(d-1,u.childNodes.length-1)]),l==u)return r(i([l]));for(f=e.findCommonAncestor(l,u),m=l;m;m=m.parentNode){if(m===u)return s(l,f,!0);if(m===f)break}for(m=u;m;m=m.parentNode){if(m===l)return s(u,f);if(m===f)break}p=a(l,f)||l,h=a(u,f)||u,s(l,p,!0),v=o(p==l?p:p.nextSibling,"nextSibling",h==u?h.nextSibling:h),v.length&&r(i(v)),s(u,h)},this.split=function(e){function t(e,t){return e.splitText(t)}var n=e.startContainer,r=e.startOffset,i=e.endContainer,o=e.endOffset;return n==i&&3==n.nodeType?r>0&&r<n.nodeValue.length&&(i=t(n,r),n=i.previousSibling,o>r?(o-=r,n=i=t(i,o).previousSibling,o=i.nodeValue.length,r=0):o=0):(3==n.nodeType&&r>0&&r<n.nodeValue.length&&(n=t(n,r),r=0),3==i.nodeType&&o>0&&o<i.nodeValue.length&&(i=t(i,o).previousSibling,o=i.nodeValue.length)),{startContainer:n,startOffset:r,endContainer:i,endOffset:o}}}var n=e.each;return t.compareRanges=function(e,t){if(e&&t){if(!e.item&&!e.duplicate)return e.startContainer==t.startContainer&&e.startOffset==t.startOffset;if(e.item&&t.item&&e.item(0)===t.item(0))return!0;if(e.isEqual&&t.isEqual&&t.isEqual(e))return!0}return!1},t}),r(L,[f,B,p],function(e,t,n){return function(r){function i(e){return e.nodeType&&(e=e.nodeName),!!r.schema.getTextBlockElements()[e.toLowerCase()]}function o(e,t){return I.getParents(e,t,I.getRoot())}function a(e){return 1===e.nodeType&&"_mce_caret"===e.id}function s(){u({alignleft:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"left"},defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"left"}}],aligncenter:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"center"},defaultBlock:"div"},{selector:"img",collapsed:!1,styles:{display:"block",marginLeft:"auto",marginRight:"auto"}},{selector:"table",collapsed:!1,styles:{marginLeft:"auto",marginRight:"auto"}}],alignright:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"right"},defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"right"}}],alignjustify:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"justify"},defaultBlock:"div"}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:!0},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:!0},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},wrap_links:!1},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},wrap_links:!1},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},code:{inline:"code"},link:{inline:"a",selector:"a",remove:"all",split:!0,deep:!0,onmatch:function(){return!0},onformat:function(e,t,n){et(n,function(t,n){I.setAttrib(e,n,t)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike",remove:"all",split:!0,expand:!1,block_expand:!0,deep:!0},{selector:"span",attributes:["style","class"],remove:"empty",split:!0,expand:!1,deep:!0},{selector:"*",attributes:["style","class"],split:!1,expand:!1,deep:!0}]}),et("p h1 h2 h3 h4 h5 h6 div address pre div dt dd samp".split(/\s/),function(e){u(e,{block:e,remove:"all"})}),u(r.settings.formats)}function l(){r.addShortcut("ctrl+b","bold_desc","Bold"),r.addShortcut("ctrl+i","italic_desc","Italic"),r.addShortcut("ctrl+u","underline_desc","Underline");for(var e=1;6>=e;e++)r.addShortcut("ctrl+"+e,"",["FormatBlock",!1,"h"+e]);r.addShortcut("ctrl+7","",["FormatBlock",!1,"p"]),r.addShortcut("ctrl+8","",["FormatBlock",!1,"div"]),r.addShortcut("ctrl+9","",["FormatBlock",!1,"address"])}function c(e){return e?O[e]:O}function u(e,t){e&&("string"!=typeof e?et(e,function(e,t){u(t,e)}):(t=t.length?t:[t],et(t,function(e){e.deep===X&&(e.deep=!e.selector),e.split===X&&(e.split=!e.selector||e.inline),e.remove===X&&e.selector&&!e.inline&&(e.remove="none"),e.selector&&e.inline&&(e.mixed=!0,e.block_expand=!0),"string"==typeof e.classes&&(e.classes=e.classes.split(/\s+/))}),O[e]=t))}function d(e){var t;return r.dom.getParent(e,function(e){return t=r.dom.getStyle(e,"text-decoration"),t&&"none"!==t}),t}function f(e){var t;1===e.nodeType&&e.parentNode&&1===e.parentNode.nodeType&&(t=d(e.parentNode),r.dom.getStyle(e,"color")&&t?r.dom.setStyle(e,"text-decoration",t):r.dom.getStyle(e,"textdecoration")===t&&r.dom.setStyle(e,"text-decoration",null))}function p(t,n,o){function s(e,t){t=t||m,e&&(t.onformat&&t.onformat(e,t,n,o),et(t.styles,function(t,r){I.setStyle(e,r,E(t,n))}),et(t.attributes,function(t,r){I.setAttrib(e,r,E(t,n))}),et(t.classes,function(t){t=E(t,n),I.hasClass(e,t)||I.addClass(e,t)}))}function l(){function t(t,n){var r=new e(n);for(o=r.current();o;o=r.prev())if(o.childNodes.length>1||o==t||"BR"==o.tagName)return o}var n=r.selection.getRng(),i=n.startContainer,a=n.endContainer;if(i!=a&&0===n.endOffset){var s=t(i,a),l=3==s.nodeType?s.length:s.childNodes.length;n.setEnd(s,l)}return n}function u(e,t,n,r,i){var o=[],a=-1,s,l=-1,c=-1,u;return et(e.childNodes,function(e,t){return"UL"===e.nodeName||"OL"===e.nodeName?(a=t,s=e,!1):void 0}),et(e.childNodes,function(e,n){"SPAN"===e.nodeName&&"bookmark"==I.getAttrib(e,"data-mce-type")&&(e.id==t.id+"_start"?l=n:e.id==t.id+"_end"&&(c=n))}),0>=a||a>l&&c>a?(et(tt(e.childNodes),i),0):(u=I.clone(n,K),et(tt(e.childNodes),function(e,t){(a>l&&a>t||l>a&&t>a)&&(o.push(e),e.parentNode.removeChild(e))}),a>l?e.insertBefore(u,s):l>a&&e.insertBefore(u,s.nextSibling),r.push(u),et(o,function(e){u.appendChild(e)}),u)}function d(e,r,o){var l=[],c,d,f=!0;c=m.inline||m.block,d=I.create(c),s(d),W.walk(e,function(e){function p(e){var y,C,x,_,N;return N=f,y=e.nodeName.toLowerCase(),C=e.parentNode.nodeName.toLowerCase(),1===e.nodeType&&J(e)&&(N=f,f="true"===J(e),_=!0),w(y,"br")?(v=0,m.block&&I.remove(e),void 0):m.wrapper&&g(e,t,n)?(v=0,void 0):f&&!_&&m.block&&!m.wrapper&&i(y)&&z(C,c)?(e=I.rename(e,c),s(e),l.push(e),v=0,void 0):m.selector&&(et(h,function(t){"collapsed"in t&&t.collapsed!==b||I.is(e,t.selector)&&!a(e)&&(s(e,t),x=!0)}),!m.inline||x)?(v=0,void 0):(!f||_||!z(c,y)||!z(C,c)||!o&&3===e.nodeType&&1===e.nodeValue.length&&65279===e.nodeValue.charCodeAt(0)||a(e)||m.inline&&V(e)?"li"==y&&r?v=u(e,r,d,l,p):(v=0,et(tt(e.childNodes),p),_&&(f=N),v=0):(v||(v=I.clone(d,K),e.parentNode.insertBefore(v,e),l.push(v)),v.appendChild(e)),void 0)}var v;et(e,p)}),m.wrap_links===!1&&et(l,function(e){function t(e){var n,r,i;if("A"===e.nodeName){for(r=I.clone(d,K),l.push(r),i=tt(e.childNodes),n=0;n<i.length;n++)r.appendChild(i[n]);e.appendChild(r)}et(tt(e.childNodes),t)}t(e)}),et(l,function(e){function r(e){var t=0;return et(e.childNodes,function(e){S(e)||L(e)||t++}),t}function i(e){var t,n;return et(e.childNodes,function(e){return 1!=e.nodeType||L(e)||a(e)?void 0:(t=e,K)}),t&&x(t,m)&&(n=I.clone(t,K),s(n),I.replace(n,e,G),I.remove(t,1)),n||e}var o;if(o=r(e),(l.length>1||!V(e))&&0===o)return I.remove(e,1),void 0;if(m.inline||m.wrapper){if(m.exact||1!==o||(e=i(e)),et(h,function(t){et(I.select(t.inline,e),function(e){var r;if(t.wrap_links===!1){r=e.parentNode;do if("A"===r.nodeName)return;while(r=r.parentNode)}R(t,n,e,t.exact?e:null)})}),g(e.parentNode,t,n))return I.remove(e,1),e=0,G;m.merge_with_parents&&I.getParent(e.parentNode,function(r){return g(r,t,n)?(I.remove(e,1),e=0,G):void 0}),e&&m.merge_siblings!==!1&&(e=M(B(e),e),e=M(e,B(e,G)))}})}var h=c(t),m=h[0],v,y,b=!o&&F.isCollapsed();if(m)if(o)o.nodeType?(y=I.createRng(),y.setStartBefore(o),y.setEndAfter(o),d(T(y,h),null,!0)):d(o,null,!0);else if(b&&m.inline&&!I.select("td.mce-item-selected,th.mce-item-selected").length)H("apply",t,n);else{var C=r.selection.getNode();U||!h[0].defaultBlock||I.getParent(C,I.isBlock)||p(h[0].defaultBlock),r.selection.setRng(l()),v=F.getBookmark(),d(T(F.getRng(G),h),v),m.styles&&(m.styles.color||m.styles.textDecoration)&&(nt(C,f,"childNodes"),f(C)),F.moveToBookmark(v),P(F.getRng(G)),r.nodeChanged()}}function h(e,t,n){function i(e){var n,r,o,a,s;if(1===e.nodeType&&J(e)&&(a=b,b="true"===J(e),s=!0),n=tt(e.childNodes),b&&!s)for(r=0,o=p.length;o>r&&!R(p[r],t,e,e);r++);if(h.deep&&n.length){for(r=0,o=n.length;o>r;r++)i(n[r]);s&&(b=a)}}function a(n){var r;return et(o(n.parentNode).reverse(),function(n){var i;r||"_start"==n.id||"_end"==n.id||(i=g(n,e,t),i&&i.split!==!1&&(r=n))}),r}function s(e,n,r,i){var o,a,s,l,c,u;if(e){for(u=e.parentNode,o=n.parentNode;o&&o!=u;o=o.parentNode){for(a=I.clone(o,K),c=0;c<p.length;c++)if(R(p[c],t,a,a)){a=0;break}a&&(s&&a.appendChild(s),l||(l=a),s=a)}!i||h.mixed&&V(e)||(n=I.split(e,n)),s&&(r.parentNode.insertBefore(s,r),l.appendChild(r))}return n}function l(e){return s(a(e),e,e,!0)}function u(e){var t=I.get(e?"_start":"_end"),n=t[e?"firstChild":"lastChild"];return L(n)&&(n=n[e?"firstChild":"lastChild"]),I.remove(t,!0),n}function f(e){var t,n;e=T(e,p,G),h.split&&(t=D(e,G),n=D(e),t!=n?(/^(TR|TD)$/.test(t.nodeName)&&t.firstChild&&(t="TD"==t.nodeName?t.firstChild||t:t.firstChild.firstChild||t),t=k(t,"span",{id:"_start","data-mce-type":"bookmark"}),n=k(n,"span",{id:"_end","data-mce-type":"bookmark"}),l(t),l(n),t=u(G),n=u()):t=n=l(t),e.startContainer=t.parentNode,e.startOffset=q(t),e.endContainer=n.parentNode,e.endOffset=q(n)+1),W.walk(e,function(e){et(e,function(e){i(e),1===e.nodeType&&"underline"===r.dom.getStyle(e,"text-decoration")&&e.parentNode&&"underline"===d(e.parentNode)&&R({deep:!1,exact:!0,inline:"span",styles:{textDecoration:"underline"}},null,e)})})}var p=c(e),h=p[0],m,y,b=!0;return n?(n.nodeType?(y=I.createRng(),y.setStartBefore(n),y.setEndAfter(n),f(y)):f(n),void 0):(F.isCollapsed()&&h.inline&&!I.select("td.mce-item-selected,th.mce-item-selected").length?H("remove",e,t):(m=F.getBookmark(),f(F.getRng(G)),F.moveToBookmark(m),h.inline&&v(e,t,F.getStart())&&P(F.getRng(!0)),r.nodeChanged()),void 0)}function m(e,t,n){var r=c(e);!v(e,t,n)||"toggle"in r[0]&&!r[0].toggle?p(e,t,n):h(e,t,n)}function g(e,t,n,r){function i(e,t,i){var o,a,s=t[i],l;if(t.onmatch)return t.onmatch(e,t,i);if(s)if(s.length===X){for(o in s)if(s.hasOwnProperty(o)){if(a="attributes"===i?I.getAttrib(e,o):_(e,o),r&&!a&&!t.exact)return;if((!r||t.exact)&&!w(a,N(E(s[o],n),o)))return}}else for(l=0;l<s.length;l++)if("attributes"===i?I.getAttrib(e,s[l]):_(e,s[l]))return t;return t}var o=c(t),a,s,l;if(o&&e)for(s=0;s<o.length;s++)if(a=o[s],x(e,a)&&i(e,a,"attributes")&&i(e,a,"styles")){if(l=a.classes)for(s=0;s<l.length;s++)if(!I.hasClass(e,l[s]))return;return a}}function v(e,t,n){function r(n){return n=I.getParent(n,function(n){return!!g(n,e,t,!0)}),g(n,e,t)}var i;return n?r(n):(n=F.getNode(),r(n)?G:(i=F.getStart(),i!=n&&r(i)?G:K))}function y(e,t){var n,r=[],i={};return n=F.getStart(),I.getParent(n,function(n){var o,a;for(o=0;o<e.length;o++)a=e[o],!i[a]&&g(n,a,t)&&(i[a]=!0,r.push(a))},I.getRoot()),r}function b(e){var t=c(e),n,r,i,a,s;if(t)for(n=F.getStart(),r=o(n),a=t.length-1;a>=0;a--){if(s=t[a].selector,!s)return G;for(i=r.length-1;i>=0;i--)if(I.is(r[i],s))return G}return K}function C(e,t,n){var i;return Y||(Y={},i={},r.on("NodeChange",function(e){var t=o(e.element),n={};et(Y,function(e,r){et(t,function(o){return g(o,r,{},e.similar)?(i[r]||(et(e,function(e){e(!0,{node:o,format:r,parents:t})}),i[r]=e),n[r]=e,!1):void 0})}),et(i,function(r,o){n[o]||(delete i[o],et(r,function(n){n(!1,{node:e.element,format:o,parents:t})}))})})),et(e.split(","),function(e){Y[e]||(Y[e]=[],Y[e].similar=n),Y[e].push(t)}),this}function x(e,t){return w(e,t.inline)?G:w(e,t.block)?G:t.selector?1==e.nodeType&&I.is(e,t.selector):void 0}function w(e,t){return e=e||"",t=t||"",e=""+(e.nodeName||e),t=""+(t.nodeName||t),e.toLowerCase()==t.toLowerCase()}function _(e,t){return N(I.getStyle(e,t),t)}function N(e,t){return("color"==t||"backgroundColor"==t)&&(e=I.toHex(e)),"fontWeight"==t&&700==e&&(e="bold"),"fontFamily"==t&&(e=e.replace(/[\'\"]/g,"").replace(/,\s+/g,",")),""+e}function E(e,t){return"string"!=typeof e?e=e(t):t&&(e=e.replace(/%(\w+)/g,function(e,n){return t[n]||e})),e}function S(e){return e&&3===e.nodeType&&/^([\t \r\n]+|)$/.test(e.nodeValue)}function k(e,t,n){var r=I.create(t,n);return e.parentNode.insertBefore(r,e),r.appendChild(e),r}function T(t,n,a){function s(e){function t(e){return"BR"==e.nodeName&&e.getAttribute("data-mce-bogus")&&!e.nextSibling}var r,i,o,a,s;if(r=i=e?g:y,a=e?"previousSibling":"nextSibling",s=I.getRoot(),3==r.nodeType&&!S(r)&&(e?v>0:b<r.nodeValue.length))return r;for(;;){if(!n[0].block_expand&&V(i))return i;for(o=i[a];o;o=o[a])if(!L(o)&&!S(o)&&!t(o))return i;if(i.parentNode==s){r=i;break}i=i.parentNode}return r}function l(e,t){for(t===X&&(t=3===e.nodeType?e.length:e.childNodes.length);e&&e.hasChildNodes();)e=e.childNodes[t],e&&(t=3===e.nodeType?e.length:e.childNodes.length);return{node:e,offset:t}}function c(e){for(var t=e;t;){if(1===t.nodeType&&J(t))return"false"===J(t)?t:e;t=t.parentNode}return e}function u(t,n,i){function o(e,t){var n,r,o=e.nodeValue;return"undefined"==typeof t&&(t=i?o.length:0),i?(n=o.lastIndexOf(" ",t),r=o.lastIndexOf("\xa0",t),n=n>r?n:r,-1===n||a||n++):(n=o.indexOf(" ",t),r=o.indexOf("\xa0",t),n=-1!==n&&(-1===r||r>n)?n:r),n}var s,l,c,u;if(3===t.nodeType){if(c=o(t,n),-1!==c)return{container:t,offset:c};u=t}for(s=new e(t,I.getParent(t,V)||r.getBody());l=s[i?"prev":"next"]();)if(3===l.nodeType){if(u=l,c=o(l),-1!==c)return{container:l,offset:c} +}else if(V(l))break;return u?(n=i?0:u.length,{container:u,offset:n}):void 0}function d(e,r){var i,a,s,l;for(3==e.nodeType&&0===e.nodeValue.length&&e[r]&&(e=e[r]),i=o(e),a=0;a<i.length;a++)for(s=0;s<n.length;s++)if(l=n[s],!("collapsed"in l&&l.collapsed!==t.collapsed)&&I.is(i[a],l.selector))return i[a];return e}function f(e,t){var r;if(n[0].wrapper||(r=I.getParent(e,n[0].block)),r||(r=I.getParent(3==e.nodeType?e.parentNode:e,i)),r&&n[0].wrapper&&(r=o(r,"ul,ol").reverse()[0]||r),!r)for(r=e;r[t]&&!V(r[t])&&(r=r[t],!w(r,"br")););return r||e}var p,h,m,g=t.startContainer,v=t.startOffset,y=t.endContainer,b=t.endOffset;if(1==g.nodeType&&g.hasChildNodes()&&(p=g.childNodes.length-1,g=g.childNodes[v>p?p:v],3==g.nodeType&&(v=0)),1==y.nodeType&&y.hasChildNodes()&&(p=y.childNodes.length-1,y=y.childNodes[b>p?p:b-1],3==y.nodeType&&(b=y.nodeValue.length)),g=c(g),y=c(y),(L(g.parentNode)||L(g))&&(g=L(g)?g:g.parentNode,g=g.nextSibling||g,3==g.nodeType&&(v=0)),(L(y.parentNode)||L(y))&&(y=L(y)?y:y.parentNode,y=y.previousSibling||y,3==y.nodeType&&(b=y.length)),n[0].inline&&(t.collapsed&&(m=u(g,v,!0),m&&(g=m.container,v=m.offset),m=u(y,b),m&&(y=m.container,b=m.offset)),h=l(y,b),h.node)){for(;h.node&&0===h.offset&&h.node.previousSibling;)h=l(h.node.previousSibling);h.node&&h.offset>0&&3===h.node.nodeType&&" "===h.node.nodeValue.charAt(h.offset-1)&&h.offset>1&&(y=h.node,y.splitText(h.offset-1))}return(n[0].inline||n[0].block_expand)&&(n[0].inline&&3==g.nodeType&&0!==v||(g=s(!0)),n[0].inline&&3==y.nodeType&&b!==y.nodeValue.length||(y=s())),n[0].selector&&n[0].expand!==K&&!n[0].inline&&(g=d(g,"previousSibling"),y=d(y,"nextSibling")),(n[0].block||n[0].selector)&&(g=f(g,"previousSibling"),y=f(y,"nextSibling"),n[0].block&&(V(g)||(g=s(!0)),V(y)||(y=s()))),1==g.nodeType&&(v=q(g),g=g.parentNode),1==y.nodeType&&(b=q(y)+1,y=y.parentNode),{startContainer:g,startOffset:v,endContainer:y,endOffset:b}}function R(e,t,n,r){var i,o,a;if(!x(n,e))return K;if("all"!=e.remove)for(et(e.styles,function(e,i){e=N(E(e,t),i),"number"==typeof i&&(i=e,r=0),(!r||w(_(r,i),e))&&I.setStyle(n,i,""),a=1}),a&&""===I.getAttrib(n,"style")&&(n.removeAttribute("style"),n.removeAttribute("data-mce-style")),et(e.attributes,function(e,i){var o;if(e=E(e,t),"number"==typeof i&&(i=e,r=0),!r||w(I.getAttrib(r,i),e)){if("class"==i&&(e=I.getAttrib(n,i),e&&(o="",et(e.split(/\s+/),function(e){/mce\w+/.test(e)&&(o+=(o?" ":"")+e)}),o)))return I.setAttrib(n,i,o),void 0;"class"==i&&n.removeAttribute("className"),j.test(i)&&n.removeAttribute("data-mce-"+i),n.removeAttribute(i)}}),et(e.classes,function(e){e=E(e,t),(!r||I.hasClass(r,e))&&I.removeClass(n,e)}),o=I.getAttribs(n),i=0;i<o.length;i++)if(0!==o[i].nodeName.indexOf("_"))return K;return"none"!=e.remove?(A(n,e),G):void 0}function A(e,t){function n(e,t,n){return e=B(e,t,n),!e||"BR"==e.nodeName||V(e)}var r=e.parentNode,i;t.block&&(U?r==I.getRoot()&&(t.list_block&&w(e,t.list_block)||et(tt(e.childNodes),function(e){z(U,e.nodeName.toLowerCase())?i?i.appendChild(e):i=k(e,U):i=0})):V(e)&&!V(r)&&(n(e,K)||n(e.firstChild,G,1)||e.insertBefore(I.create("br"),e.firstChild),n(e,G)||n(e.lastChild,K,1)||e.appendChild(I.create("br")))),t.selector&&t.inline&&!w(t.inline,e)||I.remove(e,1)}function B(e,t,n){if(e)for(t=t?"nextSibling":"previousSibling",e=n?e:e[t];e;e=e[t])if(1==e.nodeType||!S(e))return e}function L(e){return e&&1==e.nodeType&&"bookmark"==e.getAttribute("data-mce-type")}function M(e,t){function n(e,t){function n(e){var t={};return et(I.getAttribs(e),function(n){var r=n.nodeName.toLowerCase();0!==r.indexOf("_")&&"style"!==r&&(t[r]=I.getAttrib(e,r))}),t}function r(e,t){var n,r;for(r in e)if(e.hasOwnProperty(r)){if(n=t[r],n===X)return K;if(e[r]!=n)return K;delete t[r]}for(r in t)if(t.hasOwnProperty(r))return K;return G}return e.nodeName!=t.nodeName?K:r(n(e),n(t))?r(I.parseStyle(I.getAttrib(e,"style")),I.parseStyle(I.getAttrib(t,"style")))?G:K:K}function r(e,t){for(i=e;i;i=i[t]){if(3==i.nodeType&&0!==i.nodeValue.length)return e;if(1==i.nodeType&&!L(i))return i}return e}var i,o;if(e&&t&&(e=r(e,"previousSibling"),t=r(t,"nextSibling"),n(e,t))){for(i=e.nextSibling;i&&i!=t;)o=i,i=i.nextSibling,e.appendChild(o);return I.remove(t),et(tt(t.childNodes),function(t){e.appendChild(t)}),e}return t}function D(t,n){var i,o,a;return i=t[n?"startContainer":"endContainer"],o=t[n?"startOffset":"endOffset"],1==i.nodeType&&(a=i.childNodes.length-1,!n&&o&&o--,i=i.childNodes[o>a?a:o]),3===i.nodeType&&n&&o>=i.nodeValue.length&&(i=new e(i,r.getBody()).next()||i),3!==i.nodeType||n||0!==o||(i=new e(i,r.getBody()).prev()||i),i}function H(t,n,o){function a(e){var t=I.create("span",{id:y,"data-mce-bogus":!0,style:b?"color:red":""});return e&&t.appendChild(r.getDoc().createTextNode($)),t}function s(e,t){for(;e;){if(3===e.nodeType&&e.nodeValue!==$||e.childNodes.length>1)return!1;t&&1===e.nodeType&&t.push(e),e=e.firstChild}return!0}function l(e){for(;e;){if(e.id===y)return e;e=e.parentNode}}function u(t){var n;if(t)for(n=new e(t,t),t=n.current();t;t=n.next())if(3===t.nodeType)return t}function d(e,t){var n,r;if(e)r=F.getRng(!0),s(e)?(t!==!1&&(r.setStartBefore(e),r.setEndBefore(e)),I.remove(e)):(n=u(e),n.nodeValue.charAt(0)===$&&(n=n.deleteData(0,1)),I.remove(e,1)),F.setRng(r);else if(e=l(F.getStart()),!e)for(;e=I.get(y);)d(e,!1)}function f(){var e,t,r,i,s,d,f;e=F.getRng(!0),i=e.startOffset,d=e.startContainer,f=d.nodeValue,t=l(F.getStart()),t&&(r=u(t)),f&&i>0&&i<f.length&&/\w/.test(f.charAt(i))&&/\w/.test(f.charAt(i-1))?(s=F.getBookmark(),e.collapse(!0),e=T(e,c(n)),e=W.split(e),p(n,o,e),F.moveToBookmark(s)):(t&&r.nodeValue===$?p(n,o,t):(t=a(!0),r=t.firstChild,e.insertNode(t),i=1,p(n,o,t)),F.setCursorLocation(r,i))}function m(){var e=F.getRng(!0),t,r,s,l,u,d,f=[],p,m;for(t=e.startContainer,r=e.startOffset,u=t,3==t.nodeType&&((r!=t.nodeValue.length||t.nodeValue===$)&&(l=!0),u=u.parentNode);u;){if(g(u,n,o)){d=u;break}u.nextSibling&&(l=!0),f.push(u),u=u.parentNode}if(d)if(l)s=F.getBookmark(),e.collapse(!0),e=T(e,c(n),!0),e=W.split(e),h(n,o,e),F.moveToBookmark(s);else{for(m=a(),u=m,p=f.length-1;p>=0;p--)u.appendChild(I.clone(f[p],!1)),u=u.firstChild;u.appendChild(I.doc.createTextNode($)),u=u.firstChild;var v=I.getParent(d,i);v&&I.isEmpty(v)?d.parentNode.replaceChild(m,d):I.insertAfter(m,d),F.setCursorLocation(u,1)}}function v(){var e;e=l(F.getStart()),e&&!I.isEmpty(e)&&nt(e,function(e){1!=e.nodeType||e.id===y||I.isEmpty(e)||I.setAttrib(e,"data-mce-bogus",null)},"childNodes")}var y="_mce_caret",b=r.settings.caret_debug;r._hasCaretEvents||(Z=function(){var e=[],t;if(s(l(F.getStart()),e))for(t=e.length;t--;)I.setAttrib(e[t],"data-mce-bogus","1")},Q=function(e){var t=e.keyCode;d(),(8==t||37==t||39==t)&&d(l(F.getStart())),v()},r.on("SetContent",function(e){e.selection&&v()}),r._hasCaretEvents=!0),"apply"==t?f():m()}function P(t){var n=t.startContainer,r=t.startOffset,i,o,a,s,l;if(3==n.nodeType&&r>=n.nodeValue.length&&(r=q(n),n=n.parentNode,i=!0),1==n.nodeType)for(s=n.childNodes,n=s[Math.min(r,s.length-1)],o=new e(n,I.getParent(n,I.isBlock)),(r>s.length-1||i)&&o.next(),a=o.current();a;a=o.next())if(3==a.nodeType&&!S(a))return l=I.create("a",null,$),a.parentNode.insertBefore(l,a),t.setStart(a,0),F.setRng(t),I.remove(l),void 0}var O={},I=r.dom,F=r.selection,W=new t(I),z=r.schema.isValidChild,V=I.isBlock,U=r.settings.forced_root_block,q=I.nodeIndex,$="\ufeff",j=/^(src|href|style)$/,K=!1,G=!0,Y,X,J=I.getContentEditable,Q,Z,et=n.each,tt=n.grep,nt=n.walk,rt=n.extend;rt(this,{get:c,register:u,apply:p,remove:h,toggle:m,match:v,matchAll:y,matchNode:g,canApply:b,formatChanged:C}),s(),l(),r.on("BeforeGetContent",function(){Z&&Z()}),r.on("mouseup keydown",function(e){Q&&Q(e)})}}),r(M,[g,p],function(e,t){var n=t.trim,r;return r=new RegExp(["<span[^>]+data-mce-bogus[^>]+>[\u200b\ufeff]+<\\/span>","<div[^>]+data-mce-bogus[^>]+><\\/div>",'\\s?data-mce-selected="[^"]+"'].join("|"),"gi"),function(t){function i(){return n(t.getContent({format:"raw",no_events:1}).replace(r,""))}function o(){a.typing=!1,a.add()}var a,s=0,l=[],c,u;return t.on("init",function(){a.add()}),t.on("BeforeExecCommand",function(e){var t=e.command;"Undo"!=t&&"Redo"!=t&&"mceRepaint"!=t&&a.beforeChange()}),t.on("ExecCommand",function(e){var t=e.command;"Undo"!=t&&"Redo"!=t&&"mceRepaint"!=t&&a.add()}),t.on("ObjectResizeStart",function(){a.beforeChange()}),t.on("SaveContent ObjectResized",o),t.dom.bind(t.dom.getRoot(),"dragend",o),t.dom.bind(t.getBody(),"focusout",function(){!t.removed&&a.typing&&o()}),t.on("KeyUp",function(n){var r=n.keyCode;(r>=33&&36>=r||r>=37&&40>=r||45==r||13==r||n.ctrlKey)&&(o(),t.nodeChanged()),(46==r||8==r||e.mac&&(91==r||93==r))&&t.nodeChanged(),u&&a.typing&&(t.isDirty()||(t.isNotDirty=!l[0]||i()==l[0].content),t.fire("TypingUndo"),u=!1,t.nodeChanged())}),t.on("KeyDown",function(e){var t=e.keyCode;return t>=33&&36>=t||t>=37&&40>=t||45==t?(a.typing&&o(),void 0):((16>t||t>20)&&224!=t&&91!=t&&!a.typing&&(a.beforeChange(),a.typing=!0,a.add(),u=!0),void 0)}),t.on("MouseDown",function(){a.typing&&o()}),t.addShortcut("ctrl+z","","Undo"),t.addShortcut("ctrl+y,ctrl+shift+z","","Redo"),t.on("AddUndo Undo Redo ClearUndos MouseUp",function(e){e.isDefaultPrevented()||t.nodeChanged()}),a={data:l,typing:!1,beforeChange:function(){c=t.selection.getBookmark(2,!0)},add:function(e){var n,r=t.settings,o;if(e=e||{},e.content=i(),t.fire("BeforeAddUndo",{level:e}).isDefaultPrevented())return null;if(o=l[s],o&&o.content==e.content)return null;if(l[s]&&(l[s].beforeBookmark=c),r.custom_undo_redo_levels&&l.length>r.custom_undo_redo_levels){for(n=0;n<l.length-1;n++)l[n]=l[n+1];l.length--,s=l.length}e.bookmark=t.selection.getBookmark(2,!0),s<l.length-1&&(l.length=s+1),l.push(e),s=l.length-1;var a={level:e,lastLevel:o};return t.fire("AddUndo",a),s>0&&(t.fire("change",a),t.isNotDirty=!1),e},undo:function(){var e;return a.typing&&(a.add(),a.typing=!1),s>0&&(e=l[--s],t.setContent(e.content,{format:"raw"}),t.selection.moveToBookmark(e.beforeBookmark),t.fire("undo",{level:e})),e},redo:function(){var e;return s<l.length-1&&(e=l[++s],t.setContent(e.content,{format:"raw"}),t.selection.moveToBookmark(e.bookmark),t.fire("redo",{level:e})),e},clear:function(){l=[],s=0,a.typing=!1,t.fire("ClearUndos")},hasUndo:function(){return s>0||a.typing&&l[0]&&i()!=l[0].content},hasRedo:function(){return s<l.length-1&&!this.typing},transact:function(e){a.beforeChange(),e(),a.add()}}}}),r(D,[f,g],function(e,t){var n=t.ie;return function(t){function r(r){function u(e){return e&&i.isBlock(e)&&!/^(TD|TH|CAPTION|FORM)$/.test(e.nodeName)&&!/^(fixed|absolute)/i.test(e.style.position)&&"true"!==i.getContentEditable(e)}function d(e){var t;i.isBlock(e)&&(t=o.getRng(),e.appendChild(i.create("span",null,"\xa0")),o.select(e),e.lastChild.outerHTML="",o.setRng(t))}function f(e){for(var t=e,n=[],r;t=t.firstChild;){if(i.isBlock(t))return;1!=t.nodeType||c[t.nodeName.toLowerCase()]||n.push(t)}for(r=n.length;r--;)t=n[r],!t.hasChildNodes()||t.firstChild==t.lastChild&&""===t.firstChild.nodeValue?i.remove(t):"A"==t.nodeName&&" "===(t.innerText||t.textContent)&&i.remove(t)}function p(t){var n,r,a,s=t,l;if(a=i.createRng(),t.hasChildNodes()){for(n=new e(t,t);r=n.current();){if(3==r.nodeType){a.setStart(r,0),a.setEnd(r,0);break}if(c[r.nodeName.toLowerCase()]){a.setStartBefore(r),a.setEndBefore(r);break}s=r,r=n.next()}r||(a.setStart(s,0),a.setEnd(s,0))}else"BR"==t.nodeName?t.nextSibling&&i.isBlock(t.nextSibling)?((!R||9>R)&&(l=i.create("br"),t.parentNode.insertBefore(l,t)),a.setStartBefore(t),a.setEndBefore(t)):(a.setStartAfter(t),a.setEndAfter(t)):(a.setStart(t,0),a.setEnd(t,0));o.setRng(a),i.remove(l),o.scrollIntoView(t)}function h(e){var t=S,r,o,s;if(r=e||"TABLE"==D?i.create(e||P):T.cloneNode(!1),s=r,a.keep_styles!==!1)do if(/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(t.nodeName)){if("_mce_caret"==t.id)continue;o=t.cloneNode(!1),i.setAttrib(o,"id",""),r.hasChildNodes()?(o.appendChild(r.firstChild),r.appendChild(o)):(s=o,r.appendChild(o))}while(t=t.parentNode);return n||(s.innerHTML='<br data-mce-bogus="1">'),r}function m(t){var n,r,i;if(3==S.nodeType&&(t?k>0:k<S.nodeValue.length))return!1;if(S.parentNode==T&&O&&!t)return!0;if(t&&1==S.nodeType&&S==T.firstChild)return!0;if("TABLE"===S.nodeName||S.previousSibling&&"TABLE"==S.previousSibling.nodeName)return O&&!t||!O&&t;for(n=new e(S,T),3==S.nodeType&&(t&&0===k?n.prev():t||k!=S.nodeValue.length||n.next());r=n.current();){if(1===r.nodeType){if(!r.getAttribute("data-mce-bogus")&&(i=r.nodeName.toLowerCase(),c[i]&&"br"!==i))return!1}else if(3===r.nodeType&&!/^[ \t\r\n]*$/.test(r.nodeValue))return!1;t?n.prev():n.next()}return!0}function g(e,n){var r,o,a,s,c,d,f=P||"P";if(o=i.getParent(e,i.isBlock),d=t.getBody().nodeName.toLowerCase(),!o||!u(o)){if(o=o||E,!o.hasChildNodes())return r=i.create(f),o.appendChild(r),_.setStart(r,0),_.setEnd(r,0),r;for(s=e;s.parentNode!=o;)s=s.parentNode;for(;s&&!i.isBlock(s);)a=s,s=s.previousSibling;if(a&&l.isValidChild(d,f.toLowerCase())){for(r=i.create(f),a.parentNode.insertBefore(r,a),s=a;s&&!i.isBlock(s);)c=s.nextSibling,r.appendChild(s),s=c;_.setStart(e,n),_.setEnd(e,n)}}return e}function v(){function e(e){for(var t=M[e?"firstChild":"lastChild"];t&&1!=t.nodeType;)t=t[e?"nextSibling":"previousSibling"];return t===T}function t(){var e=M.parentNode;return"LI"==e.nodeName?e:M}var n=M.parentNode.nodeName;/^(OL|UL|LI)$/.test(n)&&(P="LI"),B=P?h(P):i.create("BR"),e(!0)&&e()?"LI"==n?i.insertAfter(B,t()):i.replace(B,M):e(!0)?"LI"==n?(i.insertAfter(B,t()),B.appendChild(i.doc.createTextNode(" ")),B.appendChild(M)):M.parentNode.insertBefore(B,M):e()?(i.insertAfter(B,t()),d(B)):(M=t(),N=_.cloneRange(),N.setStartAfter(T),N.setEndAfter(M),L=N.extractContents(),i.insertAfter(L,M),i.insertAfter(B,M)),i.remove(T),p(B),s.add()}function y(){for(var t=new e(S,T),n;n=t.next();)if(c[n.nodeName.toLowerCase()]||n.length>0)return!0}function b(){var e,t,r;S&&3==S.nodeType&&k>=S.nodeValue.length&&(n||y()||(e=i.create("br"),_.insertNode(e),_.setStartAfter(e),_.setEndAfter(e),t=!0)),e=i.create("br"),_.insertNode(e),n&&"PRE"==D&&(!R||8>R)&&e.parentNode.insertBefore(i.doc.createTextNode("\r"),e),r=i.create("span",{}," "),e.parentNode.insertBefore(r,e),o.scrollIntoView(r),i.remove(r),t?(_.setStartBefore(e),_.setEndBefore(e)):(_.setStartAfter(e),_.setEndAfter(e)),o.setRng(_),s.add()}function C(e){do 3===e.nodeType&&(e.nodeValue=e.nodeValue.replace(/^[\r\n]+/,"")),e=e.firstChild;while(e)}function x(e){var t=i.getRoot(),n,r;for(n=e;n!==t&&"false"!==i.getContentEditable(n);)"true"===i.getContentEditable(n)&&(r=n),n=n.parentNode;return n!==t?r:t}function w(e){var t;n||(e.normalize(),t=e.lastChild,(!t||/^(left|right)$/gi.test(i.getStyle(t,"float",!0)))&&i.add(e,"br"))}var _=o.getRng(!0),N,E,S,k,T,R,A,B,L,M,D,H,P,O;if(!_.collapsed)return t.execCommand("Delete"),void 0;if(!r.isDefaultPrevented()&&(S=_.startContainer,k=_.startOffset,P=(a.force_p_newlines?"p":"")||a.forced_root_block,P=P?P.toUpperCase():"",R=i.doc.documentMode,A=r.shiftKey,1==S.nodeType&&S.hasChildNodes()&&(O=k>S.childNodes.length-1,S=S.childNodes[Math.min(k,S.childNodes.length-1)]||S,k=O&&3==S.nodeType?S.nodeValue.length:0),E=x(S))){if(s.beforeChange(),!i.isBlock(E)&&E!=i.getRoot())return(!P||A)&&b(),void 0;if((P&&!A||!P&&A)&&(S=g(S,k)),T=i.getParent(S,i.isBlock),M=T?i.getParent(T.parentNode,i.isBlock):null,D=T?T.nodeName.toUpperCase():"",H=M?M.nodeName.toUpperCase():"","LI"!=H||r.ctrlKey||(T=M,D=H),"LI"==D){if(!P&&A)return b(),void 0;if(i.isEmpty(T))return v(),void 0}if("PRE"==D&&a.br_in_pre!==!1){if(!A)return b(),void 0}else if(!P&&!A&&"LI"!=D||P&&A)return b(),void 0;P&&T===t.getBody()||(P=P||"P",m()?(B=/^(H[1-6]|PRE|FIGURE)$/.test(D)&&"HGROUP"!=H?h(P):h(),a.end_container_on_empty_block&&u(M)&&i.isEmpty(T)?B=i.split(M,T):i.insertAfter(B,T),p(B)):m(!0)?(B=T.parentNode.insertBefore(h(),T),d(B)):(N=_.cloneRange(),N.setEndAfter(T),L=N.extractContents(),C(L),B=L.firstChild,i.insertAfter(L,T),f(B),w(T),p(B)),i.setAttrib(B,"id",""),s.add())}}var i=t.dom,o=t.selection,a=t.settings,s=t.undoManager,l=t.schema,c=l.getNonEmptyElements();t.on("keydown",function(e){13==e.keyCode&&r(e)!==!1&&e.preventDefault()})}}),r(H,[],function(){return function(e){function t(){var t=i.getStart(),s=e.getBody(),l,c,u,d,f,p,h,m=-16777215,g,v,y,b,C;if(C=n.forced_root_block,t&&1===t.nodeType&&C){for(;t&&t!=s;){if(a[t.nodeName])return;t=t.parentNode}if(l=i.getRng(),l.setStart){c=l.startContainer,u=l.startOffset,d=l.endContainer,f=l.endOffset;try{v=e.getDoc().activeElement===s}catch(x){}}else l.item&&(t=l.item(0),l=e.getDoc().body.createTextRange(),l.moveToElementText(t)),v=l.parentElement().ownerDocument===e.getDoc(),y=l.duplicate(),y.collapse(!0),u=-1*y.move("character",m),y.collapsed||(y=l.duplicate(),y.collapse(!1),f=-1*y.move("character",m)-u);for(t=s.firstChild,b=s.nodeName.toLowerCase();t;)if((3===t.nodeType||1==t.nodeType&&!a[t.nodeName])&&o.isValidChild(b,C.toLowerCase())){if(3===t.nodeType&&0===t.nodeValue.length){h=t,t=t.nextSibling,r.remove(h);continue}p||(p=r.create(C),t.parentNode.insertBefore(p,t),g=!0),h=t,t=t.nextSibling,p.appendChild(h)}else p=null,t=t.nextSibling;if(g&&v){if(l.setStart)l.setStart(c,u),l.setEnd(d,f),i.setRng(l);else try{l=e.getDoc().body.createTextRange(),l.moveToElementText(s),l.collapse(!0),l.moveStart("character",u),f>0&&l.moveEnd("character",f),l.select()}catch(x){}e.nodeChanged()}}}var n=e.settings,r=e.dom,i=e.selection,o=e.schema,a=o.getBlockElements();n.forced_root_block&&e.on("KeyUp NodeChange",t)}}),r(P,[E,g,p],function(e,n,r){var i=r.each,o=r.extend,a=r.map,s=r.inArray,l=r.explode,c=n.gecko,u=n.ie,d=!0,f=!1;return function(n){function r(e,t,n){var r;return e=e.toLowerCase(),(r=_.exec[e])?(r(e,t,n),d):f}function p(e){var t;return e=e.toLowerCase(),(t=_.state[e])?t(e):-1}function h(e){var t;return e=e.toLowerCase(),(t=_.value[e])?t(e):f}function m(e,t){t=t||"exec",i(e,function(e,n){i(n.toLowerCase().split(","),function(n){_[t][n]=e})})}function g(e,r,i){return r===t&&(r=f),i===t&&(i=null),n.getDoc().execCommand(e,r,i)}function v(e){return E.match(e)}function y(e,r){E.toggle(e,r?{value:r}:t),n.nodeChanged()}function b(e){S=w.getBookmark(e)}function C(){w.moveToBookmark(S)}var x=n.dom,w=n.selection,_={state:{},exec:{},value:{}},N=n.settings,E=n.formatter,S;o(this,{execCommand:r,queryCommandState:p,queryCommandValue:h,addCommands:m}),m({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(e){var t=n.getDoc(),r;try{g(e)}catch(i){r=d}(r||!t.queryCommandSupported(e))&&n.windowManager.alert("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.")},unlink:function(e){w.isCollapsed()&&w.select(w.getNode()),g(e),w.collapse(f)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(e){var t=e.substring(7);"full"==t&&(t="justify"),i("left,center,right,justify".split(","),function(e){t!=e&&E.remove("align"+e)}),y("align"+t),r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(e){var t,n;g(e),t=x.getParent(w.getNode(),"ol,ul"),t&&(n=t.parentNode,/^(H[1-6]|P|ADDRESS|PRE)$/.test(n.nodeName)&&(b(),x.split(n,t),C()))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){y(e)},"ForeColor,HiliteColor,FontName":function(e,t,n){y(e,n)},FontSize:function(e,t,n){var r,i;n>=1&&7>=n&&(i=l(N.font_size_style_values),r=l(N.font_size_classes),n=r?r[n-1]||n:i[n-1]||n),y(e,n)},RemoveFormat:function(e){E.remove(e)},mceBlockQuote:function(){y("blockquote")},FormatBlock:function(e,t,n){return y(n||"p")},mceCleanup:function(){var e=w.getBookmark();n.setContent(n.getContent({cleanup:d}),{cleanup:d}),w.moveToBookmark(e)},mceRemoveNode:function(e,t,r){var i=r||w.getNode();i!=n.getBody()&&(b(),n.dom.remove(i,d),C())},mceSelectNodeDepth:function(e,t,r){var i=0;x.getParent(w.getNode(),function(e){return 1==e.nodeType&&i++==r?(w.select(e),f):void 0},n.getBody())},mceSelectNode:function(e,t,n){w.select(n)},mceInsertContent:function(t,r,i){function o(e){function t(e){return r[e]&&3==r[e].nodeType}var n,r,i;return n=w.getRng(!0),r=n.startContainer,i=n.startOffset,3==r.nodeType&&(i>0?e=e.replace(/^ /," "):t("previousSibling")||(e=e.replace(/^ /," ")),i<r.length?e=e.replace(/ (<br>|)$/," "):t("nextSibling")||(e=e.replace(/( | )(<br>|)$/," "))),e}var a,s,l,c,d,f,p,h,m,g,v,y,b,C;if(/^ | $/.test(i)&&(i=o(i)),a=n.parser,s=new e({},n.schema),b='<span id="mce_marker" data-mce-type="bookmark"></span>',f={content:i,format:"html",selection:!0},n.fire("BeforeSetContent",f),i=f.content,-1==i.indexOf("{$caret}")&&(i+="{$caret}"),i=i.replace(/\{\$caret\}/,b),w.isCollapsed()||n.getDoc().execCommand("Delete",!1,null),l=w.getNode(),f={context:l.nodeName.toLowerCase()},d=a.parse(i,f),v=d.lastChild,"mce_marker"==v.attr("id"))for(p=v,v=v.prev;v;v=v.walk(!0))if(3==v.type||!x.isBlock(v.name)){v.parent.insert(p,v,"br"===v.name);break}if(f.invalid){for(w.setContent(b),l=w.getNode(),c=n.getBody(),9==l.nodeType?l=v=c:v=l;v!==c;)l=v,v=v.parentNode;i=l==c?c.innerHTML:x.getOuterHTML(l),i=s.serialize(a.parse(i.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i,function(){return s.serialize(d)}))),l==c?x.setHTML(c,i):x.setOuterHTML(l,i)}else i=s.serialize(d),v=l.firstChild,y=l.lastChild,!v||v===y&&"BR"===v.nodeName?x.setHTML(l,i):w.setContent(i);p=x.get("mce_marker"),h=x.getRect(p),m=x.getViewPort(n.getWin()),(h.y+h.h>m.y+m.h||h.y<m.y||h.x>m.x+m.w||h.x<m.x)&&(C=u?n.getDoc().documentElement:n.getBody(),C.scrollLeft=h.x,C.scrollTop=h.y-m.h+25),g=x.createRng(),v=p.previousSibling,v&&3==v.nodeType?(g.setStart(v,v.nodeValue.length),u||(y=p.nextSibling,y&&3==y.nodeType&&(v.appendData(y.data),y.parentNode.removeChild(y)))):(g.setStartBefore(p),g.setEndBefore(p)),x.remove(p),w.setRng(g),n.fire("SetContent",f),n.addVisual()},mceInsertRawHTML:function(e,t,r){w.setContent("tiny_mce_marker"),n.setContent(n.getContent().replace(/tiny_mce_marker/g,function(){return r}))},mceToggleFormat:function(e,t,n){y(n)},mceSetContent:function(e,t,r){n.setContent(r)},"Indent,Outdent":function(e){var t,n,r;t=N.indentation,n=/[a-z%]+$/i.exec(t),t=parseInt(t,10),p("InsertUnorderedList")||p("InsertOrderedList")?g(e):(N.forced_root_block||x.getParent(w.getNode(),x.isBlock)||E.apply("div"),i(w.getSelectedBlocks(),function(i){var o;"LI"!=i.nodeName&&(o="rtl"==x.getStyle(i,"direction",!0)?"paddingRight":"paddingLeft","outdent"==e?(r=Math.max(0,parseInt(i.style[o]||0,10)-t),x.setStyle(i,o,r?r+n:"")):(r=parseInt(i.style[o]||0,10)+t+n,x.setStyle(i,o,r)))}))},mceRepaint:function(){if(c)try{b(d),w.getSel()&&w.getSel().selectAllChildren(n.getBody()),w.collapse(d),C()}catch(e){}},InsertHorizontalRule:function(){n.execCommand("mceInsertContent",!1,"<hr />")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual,n.addVisual()},mceReplaceContent:function(e,t,r){n.execCommand("mceInsertContent",!1,r.replace(/\{\$selection\}/g,w.getContent({format:"text"})))},mceInsertLink:function(e,t,n){var r;"string"==typeof n&&(n={href:n}),r=x.getParent(w.getNode(),"a"),n.href=n.href.replace(" ","%20"),r&&n.href||E.remove("link"),n.href&&E.apply("link",n,r)},selectAll:function(){var e=x.getRoot(),t=x.createRng();w.getRng().setStart?(t.setStart(e,0),t.setEnd(e,e.childNodes.length),w.setRng(t)):g("SelectAll")},mceNewDocument:function(){n.setContent("")}}),m({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(e){var t="align"+e.substring(7),n=w.isCollapsed()?[x.getParent(w.getNode(),x.isBlock)]:w.getSelectedBlocks(),r=a(n,function(e){return!!E.matchNode(e,t)});return-1!==s(r,d)},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){return v(e)},mceBlockQuote:function(){return v("blockquote")},Outdent:function(){var e;if(N.inline_styles){if((e=x.getParent(w.getStart(),x.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return d;if((e=x.getParent(w.getEnd(),x.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return d}return p("InsertUnorderedList")||p("InsertOrderedList")||!N.inline_styles&&!!x.getParent(w.getNode(),"BLOCKQUOTE")},"InsertUnorderedList,InsertOrderedList":function(e){var t=x.getParent(w.getNode(),"ul,ol");return t&&("insertunorderedlist"===e&&"UL"===t.tagName||"insertorderedlist"===e&&"OL"===t.tagName)}},"state"),m({"FontSize,FontName":function(e){var t=0,n;return(n=x.getParent(w.getNode(),"span"))&&(t="fontsize"==e?n.style.fontSize:n.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()),t}},"value"),m({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}}),r(O,[p],function(e){function t(e,i){var o=this,a,s;return e=r(e),i=o.settings=i||{},/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)?(o.source=e,void 0):(0===e.indexOf("/")&&0!==e.indexOf("//")&&(e=(i.base_uri?i.base_uri.protocol||"http":"http")+"://mce_host"+e),/^[\w\-]*:?\/\//.test(e)||(s=i.base_uri?i.base_uri.path:new t(location.href).directory,e=(i.base_uri&&i.base_uri.protocol||"http")+"://mce_host"+o.toAbsPath(s,e)),e=e.replace(/@@/g,"(mce_at)"),e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e),n(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(t,n){var r=e[n];r&&(r=r.replace(/\(mce_at\)/g,"@@")),o[t]=r}),a=i.base_uri,a&&(o.protocol||(o.protocol=a.protocol),o.userInfo||(o.userInfo=a.userInfo),o.port||"mce_host"!==o.host||(o.port=a.port),o.host&&"mce_host"!==o.host||(o.host=a.host),o.source=""),void 0)}var n=e.each,r=e.trim;return t.prototype={setPath:function(e){var t=this;e=/^(.*?)\/?(\w+)?$/.exec(e),t.path=e[0],t.directory=e[1],t.file=e[2],t.source="",t.getURI()},toRelative:function(e){var n=this,r;if("./"===e)return e;if(e=new t(e,{base_uri:n}),"mce_host"!=e.host&&n.host!=e.host&&e.host||n.port!=e.port||n.protocol!=e.protocol)return e.getURI();var i=n.getURI(),o=e.getURI();return i==o||"/"==i.charAt(i.length-1)&&i.substr(0,i.length-1)==o?i:(r=n.toRelPath(n.path,e.path),e.query&&(r+="?"+e.query),e.anchor&&(r+="#"+e.anchor),r)},toAbsolute:function(e,n){return e=new t(e,{base_uri:this}),e.getURI(this.host==e.host&&this.protocol==e.protocol?n:0)},toRelPath:function(e,t){var n,r=0,i="",o,a;if(e=e.substring(0,e.lastIndexOf("/")),e=e.split("/"),n=t.split("/"),e.length>=n.length)for(o=0,a=e.length;a>o;o++)if(o>=n.length||e[o]!=n[o]){r=o+1;break}if(e.length<n.length)for(o=0,a=n.length;a>o;o++)if(o>=e.length||e[o]!=n[o]){r=o+1;break}if(1===r)return t;for(o=0,a=e.length-(r-1);a>o;o++)i+="../";for(o=r-1,a=n.length;a>o;o++)i+=o!=r-1?"/"+n[o]:n[o];return i},toAbsPath:function(e,t){var r,i=0,o=[],a,s;for(a=/\/$/.test(t)?"/":"",e=e.split("/"),t=t.split("/"),n(e,function(e){e&&o.push(e)}),e=o,r=t.length-1,o=[];r>=0;r--)0!==t[r].length&&"."!==t[r]&&(".."!==t[r]?i>0?i--:o.push(t[r]):i++);return r=e.length-i,s=0>=r?o.reverse().join("/"):e.slice(0,r).join("/")+"/"+o.reverse().join("/"),0!==s.indexOf("/")&&(s="/"+s),a&&s.lastIndexOf("/")!==s.length-1&&(s+=a),s},getURI:function(e){var t,n=this;return(!n.source||e)&&(t="",e||(n.protocol&&(t+=n.protocol+"://"),n.userInfo&&(t+=n.userInfo+"@"),n.host&&(t+=n.host),n.port&&(t+=":"+n.port)),n.path&&(t+=n.path),n.query&&(t+="?"+n.query),n.anchor&&(t+="#"+n.anchor),n.source=t),n.source}},t}),r(I,[p],function(e){function t(){}var n=e.each,r=e.extend,i,o;return t.extend=i=function(e){function t(){var e,t,n,r;if(!o&&(r=this,r.init&&r.init.apply(r,arguments),t=r.Mixins))for(e=t.length;e--;)n=t[e],n.init&&n.init.apply(r,arguments)}function a(){return this}function s(e,t){return function(){var n=this,r=n._super,i;return n._super=c[e],i=t.apply(n,arguments),n._super=r,i}}var l=this,c=l.prototype,u,d,f;o=!0,u=new l,o=!1,e.Mixins&&(n(e.Mixins,function(t){t=t;for(var n in t)"init"!==n&&(e[n]=t[n])}),c.Mixins&&(e.Mixins=c.Mixins.concat(e.Mixins))),e.Methods&&n(e.Methods.split(","),function(t){e[t]=a}),e.Properties&&n(e.Properties.split(","),function(t){var n="_"+t;e[t]=function(e){var t=this,r;return e!==r?(t[n]=e,t):t[n]}}),e.Statics&&n(e.Statics,function(e,n){t[n]=e}),e.Defaults&&c.Defaults&&(e.Defaults=r({},c.Defaults,e.Defaults));for(d in e)f=e[d],u[d]="function"==typeof f&&c[d]?s(d,f):f;return t.prototype=u,t.constructor=t,t.extend=i,t},t}),r(F,[I,p],function(e,t){function n(e){for(var t=[],n=e.length,r;n--;)r=e[n],r.__checked||(t.push(r),r.__checked=1);for(n=t.length;n--;)delete t[n].__checked;return t}var r=/^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i,i=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,o=/^\s*|\s*$/g,a,s=e.extend({init:function(e){function t(e){return e?(e=e.toLowerCase(),function(t){return"*"===e||t.type===e}):void 0}function n(e){return e?function(t){return t._name===e}:void 0}function a(e){return e?(e=e.split("."),function(t){for(var n=e.length;n--;)if(!t.hasClass(e[n]))return!1;return!0}):void 0}function s(e,t,n){return e?function(r){var i=r[e]?r[e]():"";return t?"="===t?i===n:"*="===t?i.indexOf(n)>=0:"~="===t?(" "+i+" ").indexOf(" "+n+" ")>=0:"!="===t?i!=n:"^="===t?0===i.indexOf(n):"$="===t?i.substr(i.length-n.length)===n:!1:!!n}:void 0}function l(e){var t;return e?(e=/(?:not\((.+)\))|(.+)/i.exec(e),e[1]?(t=u(e[1],[]),function(e){return!d(e,t)}):(e=e[2],function(t,n,r){return"first"===e?0===n:"last"===e?n===r-1:"even"===e?0===n%2:"odd"===e?1===n%2:t[e]?t[e]():!1})):void 0}function c(e,i,c){function u(e){e&&i.push(e)}var d;return d=r.exec(e.replace(o,"")),u(t(d[1])),u(n(d[2])),u(a(d[3])),u(s(d[4],d[5],d[6])),u(l(d[7])),i.psuedo=!!d[7],i.direct=c,i}function u(e,t){var n=[],r,o,a;do if(i.exec(""),o=i.exec(e),o&&(e=o[3],n.push(o[1]),o[2])){r=o[3];break}while(o);for(r&&u(r,t),e=[],a=0;a<n.length;a++)">"!=n[a]&&e.push(c(n[a],[],">"===n[a-1]));return t.push(e),t}var d=this.match;this._selectors=u(e,[])},match:function(e,n){var r,i,o,a,s,l,c,u,d,f,p,h,m;for(n=n||this._selectors,r=0,i=n.length;i>r;r++){for(s=n[r],a=s.length,m=e,h=0,o=a-1;o>=0;o--)for(u=s[o];m;){for(u.psuedo&&(p=m.parent().items(),d=t.inArray(m,p),f=p.length),l=0,c=u.length;c>l;l++)if(!u[l](m,d,f)){l=c+1;break}if(l===c){h++;break}if(o===a-1)break;m=m.parent()}if(h===a)return!0}return!1},find:function(e){function t(e,n,i){var o,a,s,l,c,u=n[i];for(o=0,a=e.length;a>o;o++){for(c=e[o],s=0,l=u.length;l>s;s++)if(!u[s](c,o,a)){s=l+1;break}if(s===l)i==n.length-1?r.push(c):c.items&&t(c.items(),n,i+1);else if(u.direct)return;c.items&&t(c.items(),n,i)}}var r=[],i,o,l=this._selectors;if(e.items){for(i=0,o=l.length;o>i;i++)t(e.items(),l[i],0);o>1&&(r=n(r))}return a||(a=s.Collection),new a(r)}});return s}),r(W,[p,F,I],function(e,t,n){var r,i,o=Array.prototype.push,a=Array.prototype.slice;return i={length:0,init:function(e){e&&this.add(e)},add:function(t){var n=this;return e.isArray(t)?o.apply(n,t):t instanceof r?n.add(t.toArray()):o.call(n,t),n},set:function(e){var t=this,n=t.length,r;for(t.length=0,t.add(e),r=t.length;n>r;r++)delete t[r];return t},filter:function(e){var n=this,i,o,a=[],s,l;for("string"==typeof e?(e=new t(e),l=function(t){return e.match(t)}):l=e,i=0,o=n.length;o>i;i++)s=n[i],l(s)&&a.push(s);return new r(a)},slice:function(){return new r(a.apply(this,arguments))},eq:function(e){return-1===e?this.slice(e):this.slice(e,+e+1)},each:function(t){return e.each(this,t),this},toArray:function(){return e.toArray(this)},indexOf:function(e){for(var t=this,n=t.length;n--&&t[n]!==e;);return n},reverse:function(){return new r(e.toArray(this).reverse())},hasClass:function(e){return this[0]?this[0].hasClass(e):!1},prop:function(e,t){var n=this,r,i;return t!==r?(n.each(function(n){n[e]&&n[e](t)}),n):(i=n[0],i&&i[e]?i[e]():void 0)},exec:function(t){var n=this,r=e.toArray(arguments).slice(1);return n.each(function(e){e[t]&&e[t].apply(e,r)}),n}},e.each("fire on off show hide addClass removeClass append prepend before after reflow".split(" "),function(t){i[t]=function(){var n=e.toArray(arguments);return this.each(function(e){t in e&&e[t].apply(e,n)}),this}}),e.each("text name disabled active selected checked visible parent value data".split(" "),function(e){i[e]=function(t){return this.prop(e,t) +}}),r=n.extend(i),t.Collection=r,r}),r(z,[p,v],function(e,t){return{id:function(){return t.DOM.uniqueId()},createFragment:function(e){return t.DOM.createFragment(e)},getWindowSize:function(){return t.DOM.getViewPort()},getSize:function(e){return t.DOM.getSize(e)},getPos:function(e,n){return t.DOM.getPos(e,n)},getViewPort:function(e){return t.DOM.getViewPort(e)},get:function(e){return document.getElementById(e)},addClass:function(e,n){return t.DOM.addClass(e,n)},removeClass:function(e,n){return t.DOM.removeClass(e,n)},hasClass:function(e,n){return t.DOM.hasClass(e,n)},toggleClass:function(e,n,r){return t.DOM.toggleClass(e,n,r)},css:function(e,n,r){return t.DOM.setStyle(e,n,r)},on:function(e,n,r,i){return t.DOM.bind(e,n,r,i)},off:function(e,n,r){return t.DOM.unbind(e,n,r)},fire:function(e,n,r){return t.DOM.fire(e,n,r)}}}),r(V,[I,p,W,z],function(e,t,n,r){var i=t.makeMap("focusin focusout scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave wheel keydown keypress keyup contextmenu"," "),o={},a="onmousewheel"in document,s=!1,l=e.extend({Statics:{controlIdLookup:{}},classPrefix:"mce-",init:function(e){var n=this,i,o;if(n.settings=e=t.extend({},n.Defaults,e),n._id=r.id(),n._text=n._name="",n._width=n._height=0,n._aria={role:e.role},i=e.classes)for(i=i.split(" "),i.map={},o=i.length;o--;)i.map[i[o]]=!0;n._classes=i||[],n.visible(!0),t.each("title text width height name classes visible disabled active value".split(" "),function(t){var r=e[t],i;r!==i?n[t](r):n["_"+t]===i&&(n["_"+t]=!1)}),n.on("click",function(){return n.disabled()?!1:void 0}),e.classes&&t.each(e.classes.split(" "),function(e){n.addClass(e)}),n.settings=e,n._borderBox=n.parseBox(e.border),n._paddingBox=n.parseBox(e.padding),n._marginBox=n.parseBox(e.margin),e.hidden&&n.hide()},Properties:"parent,title,text,width,height,disabled,active,name,value",Methods:"renderHtml",getContainerElm:function(){return document.body},getParentCtrl:function(e){for(var t;e&&!(t=l.controlIdLookup[e.id]);)e=e.parentNode;return t},parseBox:function(e){var t,n=10;if(e)return"number"==typeof e?(e=e||0,{top:e,left:e,bottom:e,right:e}):(e=e.split(" "),t=e.length,1===t?e[1]=e[2]=e[3]=e[0]:2===t?(e[2]=e[0],e[3]=e[1]):3===t&&(e[3]=e[1]),{top:parseInt(e[0],n)||0,right:parseInt(e[1],n)||0,bottom:parseInt(e[2],n)||0,left:parseInt(e[3],n)||0})},borderBox:function(){return this._borderBox},paddingBox:function(){return this._paddingBox},marginBox:function(){return this._marginBox},measureBox:function(e,t){function n(t){var n=document.defaultView;return n?(t=t.replace(/[A-Z]/g,function(e){return"-"+e}),n.getComputedStyle(e,null).getPropertyValue(t)):e.currentStyle[t]}function r(e){var t=parseInt(n(e),10);return isNaN(t)?0:t}return{top:r(t+"TopWidth"),right:r(t+"RightWidth"),bottom:r(t+"BottomWidth"),left:r(t+"LeftWidth")}},initLayoutRect:function(){var e=this,t=e.settings,n,r,i=e.getEl(),o,a,s,l,c,u,d;n=e._borderBox=e._borderBox||e.measureBox(i,"border"),e._paddingBox=e._paddingBox||e.measureBox(i,"padding"),e._marginBox=e._marginBox||e.measureBox(i,"margin"),u=t.minWidth,d=t.minHeight,s=u||i.offsetWidth,l=d||i.offsetHeight,o=t.width,a=t.height,c=t.autoResize,c="undefined"!=typeof c?c:!o&&!a,o=o||s,a=a||l;var f=n.left+n.right,p=n.top+n.bottom,h=t.maxWidth||65535,m=t.maxHeight||65535;return e._layoutRect=r={x:t.x||0,y:t.y||0,w:o,h:a,deltaW:f,deltaH:p,contentW:o-f,contentH:a-p,innerW:o-f,innerH:a-p,startMinWidth:u||0,startMinHeight:d||0,minW:Math.min(s,h),minH:Math.min(l,m),maxW:h,maxH:m,autoResize:c,scrollW:0},e._lastLayoutRect={},r},layoutRect:function(e){var t=this,n=t._layoutRect,r,i,o,a,s,c;return n||(n=t.initLayoutRect()),e?(o=n.deltaW,a=n.deltaH,e.x!==s&&(n.x=e.x),e.y!==s&&(n.y=e.y),e.minW!==s&&(n.minW=e.minW),e.minH!==s&&(n.minH=e.minH),i=e.w,i!==s&&(i=i<n.minW?n.minW:i,i=i>n.maxW?n.maxW:i,n.w=i,n.innerW=i-o),i=e.h,i!==s&&(i=i<n.minH?n.minH:i,i=i>n.maxH?n.maxH:i,n.h=i,n.innerH=i-a),i=e.innerW,i!==s&&(i=i<n.minW-o?n.minW-o:i,i=i>n.maxW-o?n.maxW-o:i,n.innerW=i,n.w=i+o),i=e.innerH,i!==s&&(i=i<n.minH-a?n.minH-a:i,i=i>n.maxH-a?n.maxH-a:i,n.innerH=i,n.h=i+a),e.contentW!==s&&(n.contentW=e.contentW),e.contentH!==s&&(n.contentH=e.contentH),r=t._lastLayoutRect,(r.x!==n.x||r.y!==n.y||r.w!==n.w||r.h!==n.h)&&(c=l.repaintControls,c&&c.map&&!c.map[t._id]&&(c.push(t),c.map[t._id]=!0),r.x=n.x,r.y=n.y,r.w=n.w,r.h=n.h),t):n},repaint:function(){var e=this,t,n,r,i,o=0,a=0,s;t=e.getEl().style,r=e._layoutRect,s=e._lastRepaintRect||{},i=e._borderBox,o=i.left+i.right,a=i.top+i.bottom,r.x!==s.x&&(t.left=r.x+"px",s.x=r.x),r.y!==s.y&&(t.top=r.y+"px",s.y=r.y),r.w!==s.w&&(t.width=r.w-o+"px",s.w=r.w),r.h!==s.h&&(t.height=r.h-a+"px",s.h=r.h),e._hasBody&&r.innerW!==s.innerW&&(n=e.getEl("body").style,n.width=r.innerW+"px",s.innerW=r.innerW),e._hasBody&&r.innerH!==s.innerH&&(n=n||e.getEl("body").style,n.height=r.innerH+"px",s.innerH=r.innerH),e._lastRepaintRect=s,e.fire("repaint",{},!1)},on:function(e,t){function n(e){var t,n;return function(i){return t||r.parents().each(function(r){var i=r.settings.callbacks;return i&&(t=i[e])?(n=r,!1):void 0}),t.call(n,i)}}var r=this,o,a,s,l;if(t)for("string"==typeof t&&(t=n(t)),s=e.toLowerCase().split(" "),l=s.length;l--;)e=s[l],o=r._bindings,o||(o=r._bindings={}),a=o[e],a||(a=o[e]=[]),a.push(t),i[e]&&(r._nativeEvents?r._nativeEvents[e]=!0:r._nativeEvents={name:!0},r._rendered&&r.bindPendingEvents());return r},off:function(e,t){var n=this,r,i=n._bindings,o,a,s,l;if(i)if(e)for(s=e.toLowerCase().split(" "),r=s.length;r--;){if(e=s[r],o=i[e],!e){for(a in i)i[a].length=0;return n}if(o)if(t)for(l=o.length;l--;)o[l]===t&&o.splice(l,1);else o.length=0}else n._bindings=[];return n},fire:function(e,t,n){function r(){return!1}function i(){return!0}var o=this,a,s,l,c;if(e=e.toLowerCase(),t=t||{},t.type||(t.type=e),t.control||(t.control=o),t.preventDefault||(t.preventDefault=function(){t.isDefaultPrevented=i},t.stopPropagation=function(){t.isPropagationStopped=i},t.stopImmediatePropagation=function(){t.isImmediatePropagationStopped=i},t.isDefaultPrevented=r,t.isPropagationStopped=r,t.isImmediatePropagationStopped=r),o._bindings&&(l=o._bindings[e]))for(a=0,s=l.length;s>a&&(t.isImmediatePropagationStopped()||l[a].call(o,t)!==!1);a++);if(n!==!1)for(c=o.parent();c&&!t.isPropagationStopped();)c.fire(e,t,!1),c=c.parent();return t},parents:function(e){var t=this,r=new n;for(t=t.parent();t;t=t.parent())r.add(t);return e&&(r=r.filter(e)),r},next:function(){var e=this.parent().items();return e[e.indexOf(this)+1]},prev:function(){var e=this.parent().items();return e[e.indexOf(this)-1]},findCommonAncestor:function(e,t){for(var n;e;){for(n=t;n&&e!=n;)n=n.parent();if(e==n)break;e=e.parent()}return e},hasClass:function(e,t){var n=this._classes[t||"control"];return e=this.classPrefix+e,n&&!!n.map[e]},addClass:function(e,t){var n=this,r,i;return e=this.classPrefix+e,r=n._classes[t||"control"],r||(r=[],r.map={},n._classes[t||"control"]=r),r.map[e]||(r.map[e]=e,r.push(e),n._rendered&&(i=n.getEl(t),i&&(i.className=r.join(" ")))),n},removeClass:function(e,t){var n=this,r,i,o;if(e=this.classPrefix+e,r=n._classes[t||"control"],r&&r.map[e])for(delete r.map[e],i=r.length;i--;)r[i]===e&&r.splice(i,1);return n._rendered&&(o=n.getEl(t),o&&(o.className=r.join(" "))),n},toggleClass:function(e,t,n){var r=this;return t?r.addClass(e,n):r.removeClass(e,n),r},classes:function(e){var t=this._classes[e||"control"];return t?t.join(" "):""},getEl:function(e,t){var n,i=e?this._id+"-"+e:this._id;return n=o[i]=(t===!0?null:o[i])||r.get(i)},visible:function(e){var t=this,n;return"undefined"!=typeof e?(t._visible!==e&&(t._rendered&&(t.getEl().style.display=e?"":"none"),t._visible=e,n=t.parent(),n&&(n._lastRect=null),t.fire(e?"show":"hide")),t):t._visible},show:function(){return this.visible(!0)},hide:function(){return this.visible(!1)},focus:function(){try{this.getEl().focus()}catch(e){}return this},blur:function(){return this.getEl().blur(),this},aria:function(e,t){var n=this,r=n.getEl();return"undefined"==typeof t?n._aria[e]:(n._aria[e]=t,n._rendered&&("label"==e&&r.setAttribute("aria-labeledby",n._id),r.setAttribute("role"==e?e:"aria-"+e,t)),n)},encode:function(e,t){return t!==!1&&l.translate&&(e=l.translate(e)),(e||"").replace(/[&<>"]/g,function(e){return"&#"+e.charCodeAt(0)+";"})},before:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t),!0),t},after:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t)),t},remove:function(){var e=this,t=e.getEl(),n=e.parent(),i;if(e.items)for(var o=e.items().toArray(),a=o.length;a--;)o[a].remove();return n&&n.items&&(i=[],n.items().each(function(t){t!==e&&i.push(t)}),n.items().set(i),n._lastRect=null),e._eventsRoot&&e._eventsRoot==e&&r.off(t),delete l.controlIdLookup[e._id],t.parentNode&&t.parentNode.removeChild(t),e},renderBefore:function(e){var t=this;return e.parentNode.insertBefore(r.createFragment(t.renderHtml()),e),t.postRender(),t},renderTo:function(e){var t=this;return e=e||t.getContainerElm(),e.appendChild(r.createFragment(t.renderHtml())),t.postRender(),t},postRender:function(){var e=this,t=e.settings,n,i,o,a,s;for(a in t)0===a.indexOf("on")&&e.on(a.substr(2),t[a]);if(e._eventsRoot){for(o=e.parent();!s&&o;o=o.parent())s=o._eventsRoot;if(s)for(a in s._nativeEvents)e._nativeEvents[a]=!0}e.bindPendingEvents(),t.style&&(n=e.getEl(),n&&(n.setAttribute("style",t.style),n.style.cssText=t.style)),e._visible||r.css(e.getEl(),"display","none"),e.settings.border&&(i=e.borderBox(),r.css(e.getEl(),{"border-top-width":i.top,"border-right-width":i.right,"border-bottom-width":i.bottom,"border-left-width":i.left})),l.controlIdLookup[e._id]=e;for(var c in e._aria)e.aria(c,e._aria[c]);e.fire("postrender",{},!1)},scrollIntoView:function(e){function t(e,t){var n,r,i=e;for(n=r=0;i&&i!=t&&i.nodeType;)n+=i.offsetLeft||0,r+=i.offsetTop||0,i=i.offsetParent;return{x:n,y:r}}var n=this.getEl(),r=n.parentNode,i,o,a,s,l,c,u=t(n,r);return i=u.x,o=u.y,a=n.offsetWidth,s=n.offsetHeight,l=r.clientWidth,c=r.clientHeight,"end"==e?(i-=l-a,o-=c-s):"center"==e&&(i-=l/2-a/2,o-=c/2-s/2),r.scrollLeft=i,r.scrollTop=o,this},bindPendingEvents:function(){function e(e){var t=o.getParentCtrl(e.target);t&&t.fire(e.type,e)}function t(){var e=d._lastHoverCtrl;e&&(e.fire("mouseleave",{target:e.getEl()}),e.parents().each(function(e){e.fire("mouseleave",{target:e.getEl()})}),d._lastHoverCtrl=null)}function n(e){var t=o.getParentCtrl(e.target),n=d._lastHoverCtrl,r=0,i,a,s;if(t!==n){if(d._lastHoverCtrl=t,a=t.parents().toArray().reverse(),a.push(t),n){for(s=n.parents().toArray().reverse(),s.push(n),r=0;r<s.length&&a[r]===s[r];r++);for(i=s.length-1;i>=r;i--)n=s[i],n.fire("mouseleave",{target:n.getEl()})}for(i=r;i<a.length;i++)t=a[i],t.fire("mouseenter",{target:t.getEl()})}}function i(e){e.preventDefault(),"mousewheel"==e.type?(e.deltaY=-1/40*e.wheelDelta,e.wheelDeltaX&&(e.deltaX=-1/40*e.wheelDeltaX)):(e.deltaX=0,e.deltaY=e.detail),e=o.fire("wheel",e)}var o=this,l,c,u,d,f,p;if(o._rendered=!0,f=o._nativeEvents){for(u=o.parents().toArray(),u.unshift(o),l=0,c=u.length;!d&&c>l;l++)d=u[l]._eventsRoot;for(d||(d=u[u.length-1]||o),o._eventsRoot=d,c=l,l=0;c>l;l++)u[l]._eventsRoot=d;for(p in f){if(!f)return!1;"wheel"!==p||s?("mouseenter"===p||"mouseleave"===p?d._hasMouseEnter||(r.on(d.getEl(),"mouseleave",t),r.on(d.getEl(),"mouseover",n),d._hasMouseEnter=1):d[p]||(r.on(d.getEl(),p,e),d[p]=!0),f[p]=!1):a?r.on(o.getEl(),"mousewheel",i):r.on(o.getEl(),"DOMMouseScroll",i)}}},reflow:function(){return this.repaint(),this}});return l}),r(U,[],function(){var e={},t;return{add:function(t,n){e[t.toLowerCase()]=n},has:function(t){return!!e[t.toLowerCase()]},create:function(n,r){var i,o,a;if(!t){a=tinymce.ui;for(o in a)e[o.toLowerCase()]=a[o];t=!0}if("string"==typeof n?(r=r||{},r.type=n):(r=n,n=r.type),n=n.toLowerCase(),i=e[n],!i)throw new Error("Could not find control by type: "+n);return i=new i(r),i.type=n,i}}}),r(q,[V,W,F,U,p,z],function(e,t,n,r,i,o){var a={};return e.extend({layout:"",innerClass:"container-inner",init:function(e){var n=this;n._super(e),e=n.settings,n._fixed=e.fixed,n._items=new t,n.addClass("container"),n.addClass("container-body","body"),e.containerCls&&n.addClass(e.containerCls),n._layout=r.create((e.layout||n.layout)+"layout"),n.settings.items&&n.add(n.settings.items),n._hasBody=!0},items:function(){return this._items},find:function(e){return e=a[e]=a[e]||new n(e),e.find(this)},add:function(e){var t=this;return t.items().add(t.create(e)).parent(t),t},focus:function(){var e=this;return e.keyNav?e.keyNav.focusFirst():e._super(),e},replace:function(e,t){for(var n,r=this.items(),i=r.length;i--;)if(r[i]===e){r[i]=t;break}i>=0&&(n=t.getEl(),n&&n.parentNode.removeChild(n),n=e.getEl(),n&&n.parentNode.removeChild(n)),t.parent(this)},create:function(t){var n=this,o,a=[];return i.isArray(t)||(t=[t]),i.each(t,function(t){t&&(t instanceof e||("string"==typeof t&&(t={type:t}),o=i.extend({},n.settings.defaults,t),t.type=o.type=o.type||t.type||n.settings.defaultType||(o.defaults?o.defaults.type:null),t=r.create(o)),a.push(t))}),a},renderNew:function(){var e=this;return e.items().each(function(t,n){var r,i;t.parent(e),t._rendered||(r=e.getEl("body"),i=o.createFragment(t.renderHtml()),r.hasChildNodes()&&n<=r.childNodes.length-1?r.insertBefore(i,r.childNodes[n]):r.appendChild(i),t.postRender())}),e._layout.applyClasses(e),e._lastRect=null,e},append:function(e){return this.add(e).renderNew()},prepend:function(e){var t=this;return t.items().set(t.create(e).concat(t.items().toArray())),t.renderNew()},insert:function(e,t,n){var r=this,i,o,a;return e=r.create(e),i=r.items(),!n&&t<i.length-1&&(t+=1),t>=0&&t<i.length&&(o=i.slice(0,t).toArray(),a=i.slice(t).toArray(),i.set(o.concat(e,a))),r.renderNew()},fromJSON:function(e){var t=this;for(var n in e)t.find("#"+n).value(e[n]);return t},toJSON:function(){var e=this,t={};return e.find("*").each(function(e){var n=e.name(),r=e.value();n&&"undefined"!=typeof r&&(t[n]=r)}),t},preRender:function(){},renderHtml:function(){var e=this,t=e._layout;return e.preRender(),t.preRender(e),'<div id="'+e._id+'" class="'+e.classes()+'" role="'+this.settings.role+'">'+'<div id="'+e._id+'-body" class="'+e.classes("body")+'">'+(e.settings.html||"")+t.renderHtml(e)+"</div>"+"</div>"},postRender:function(){var e=this,t;return e.items().exec("postRender"),e._super(),e._layout.postRender(e),e._rendered=!0,e.settings.style&&o.css(e.getEl(),e.settings.style),e.settings.border&&(t=e.borderBox(),o.css(e.getEl(),{"border-top-width":t.top,"border-right-width":t.right,"border-bottom-width":t.bottom,"border-left-width":t.left})),e},initLayoutRect:function(){var e=this,t=e._super();return e._layout.recalc(e),t},recalc:function(){var e=this,t=e._layoutRect,n=e._lastRect;return n&&n.w==t.w&&n.h==t.h?void 0:(e._layout.recalc(e),t=e.layoutRect(),e._lastRect={x:t.x,y:t.y,w:t.w,h:t.h},!0)},reflow:function(){var t,n;if(this.visible()){for(e.repaintControls=[],e.repaintControls.map={},n=this.recalc(),t=e.repaintControls.length;t--;)e.repaintControls[t].repaint();"flow"!==this.settings.layout&&"stack"!==this.settings.layout&&this.repaint(),e.repaintControls=[]}return this}})}),r($,[z],function(e){function t(){var e=document,t,n,r,i,o,a,s,l,c=Math.max;return t=e.documentElement,n=e.body,r=c(t.scrollWidth,n.scrollWidth),i=c(t.clientWidth,n.clientWidth),o=c(t.offsetWidth,n.offsetWidth),a=c(t.scrollHeight,n.scrollHeight),s=c(t.clientHeight,n.clientHeight),l=c(t.offsetHeight,n.offsetHeight),{width:o>r?i:r,height:l>a?s:a}}return function(n,r){function i(){return a.getElementById(r.handle||n)}var o,a=document,s,l,c,u,d,f;r=r||{},l=function(n){var l=t(),p,h;n.preventDefault(),s=n.button,p=i(),d=n.screenX,f=n.screenY,h=window.getComputedStyle?window.getComputedStyle(p,null).getPropertyValue("cursor"):p.runtimeStyle.cursor,o=a.createElement("div"),e.css(o,{position:"absolute",top:0,left:0,width:l.width,height:l.height,zIndex:2147483647,opacity:1e-4,background:"red",cursor:h}),a.body.appendChild(o),e.on(a,"mousemove",u),e.on(a,"mouseup",c),r.start(n)},u=function(e){return e.button!==s?c(e):(e.deltaX=e.screenX-d,e.deltaY=e.screenY-f,e.preventDefault(),r.drag(e),void 0)},c=function(t){e.off(a,"mousemove",u),e.off(a,"mouseup",c),o.parentNode.removeChild(o),r.stop&&r.stop(t)},this.destroy=function(){e.off(i())},e.on(i(),"mousedown",l)}}),r(j,[z,$],function(e,t){return{init:function(){var e=this;e.on("repaint",e.renderScroll)},renderScroll:function(){function n(){function t(t,a,s,l,c,u){var d,f,p,h,m,g,v,y,b;if(f=i.getEl("scroll"+t)){if(y=a.toLowerCase(),b=s.toLowerCase(),i.getEl("absend")&&e.css(i.getEl("absend"),y,i.layoutRect()[l]-1),!c)return e.css(f,"display","none"),void 0;e.css(f,"display","block"),d=i.getEl("body"),p=i.getEl("scroll"+t+"t"),h=d["client"+s]-2*o,h-=n&&r?f["client"+u]:0,m=d["scroll"+s],g=h/m,v={},v[y]=d["offset"+a]+o,v[b]=h,e.css(f,v),v={},v[y]=d["scroll"+a]*g,v[b]=h*g,e.css(p,v)}}var n,r,a;a=i.getEl("body"),n=a.scrollWidth>a.clientWidth,r=a.scrollHeight>a.clientHeight,t("h","Left","Width","contentW",n,"Height"),t("v","Top","Height","contentH",r,"Width")}function r(){function n(n,r,a,s,l){var c,u=i._id+"-scroll"+n,d=i.classPrefix;i.getEl().appendChild(e.createFragment('<div id="'+u+'" class="'+d+"scrollbar "+d+"scrollbar-"+n+'">'+'<div id="'+u+'t" class="'+d+'scrollbar-thumb"></div>'+"</div>")),i.draghelper=new t(u+"t",{start:function(){c=i.getEl("body")["scroll"+r],e.addClass(e.get(u),d+"active")},drag:function(e){var t,u,d,f,p=i.layoutRect();u=p.contentW>p.innerW,d=p.contentH>p.innerH,f=i.getEl("body")["client"+a]-2*o,f-=u&&d?i.getEl("scroll"+n)["client"+l]:0,t=f/i.getEl("body")["scroll"+a],i.getEl("body")["scroll"+r]=c+e["delta"+s]/t},stop:function(){e.removeClass(e.get(u),d+"active")}})}i.addClass("scroll"),n("v","Top","Height","Y","Width"),n("h","Left","Width","X","Height")}var i=this,o=2;i.settings.autoScroll&&(i._hasScroll||(i._hasScroll=!0,r(),i.on("wheel",function(e){var t=i.getEl("body");t.scrollLeft+=10*(e.deltaX||0),t.scrollTop+=10*e.deltaY,n()}),e.on(i.getEl("body"),"scroll",n)),n())}}}),r(K,[q,j],function(e,t){return e.extend({Defaults:{layout:"fit",containerCls:"panel"},Mixins:[t],renderHtml:function(){var e=this,t=e._layout,n=e.settings.html;return e.preRender(),t.preRender(e),"undefined"==typeof n?n='<div id="'+e._id+'-body" class="'+e.classes("body")+'">'+t.renderHtml(e)+"</div>":("function"==typeof n&&(n=n.call(e)),e._hasBody=!1),'<div id="'+e._id+'" class="'+e.classes()+'" hideFocus="1" tabIndex="-1">'+(e._preBodyHtml||"")+n+"</div>"}})}),r(G,[z],function(e){function t(t,n,r){var i,o,a,s,l,c,u,d,f;return f=e.getViewPort(),o=e.getPos(n),a=o.x,s=o.y,t._fixed&&(a-=f.x,s-=f.y),i=t.getEl(),l=i.offsetWidth,c=i.offsetHeight,u=n.offsetWidth,d=n.offsetHeight,r=(r||"").split(""),"b"===r[0]&&(s+=d),"r"===r[1]&&(a+=u),"c"===r[0]&&(s+=Math.round(d/2)),"c"===r[1]&&(a+=Math.round(u/2)),"b"===r[3]&&(s-=c),"r"===r[4]&&(a-=l),"c"===r[3]&&(s-=Math.round(c/2)),"c"===r[4]&&(a-=Math.round(l/2)),{x:a,y:s,w:l,h:c}}return{testMoveRel:function(n,r){for(var i=e.getViewPort(),o=0;o<r.length;o++){var a=t(this,n,r[o]);if(this._fixed){if(a.x>0&&a.x+a.w<i.w&&a.y>0&&a.y+a.h<i.h)return r[o]}else if(a.x>i.x&&a.x+a.w<i.w+i.x&&a.y>i.y&&a.y+a.h<i.h+i.y)return r[o]}return r[0]},moveRel:function(e,n){"string"!=typeof n&&(n=this.testMoveRel(e,n));var r=t(this,e,n);return this.moveTo(r.x,r.y)},moveBy:function(e,t){var n=this,r=n.layoutRect();return n.moveTo(r.x+e,r.y+t),n},moveTo:function(t,n){function r(e,t,n){return 0>e?0:e+n>t?(e=t-n,0>e?0:e):e}var i=this;if(i.settings.constrainToViewport){var o=e.getViewPort(window),a=i.layoutRect();t=r(t,o.w+o.x,a.w),n=r(n,o.h+o.y,a.h)}return i._rendered?i.layoutRect({x:t,y:n}).repaint():(i.settings.x=t,i.settings.y=n),i.fire("move",{x:t,y:n}),i}}}),r(Y,[z],function(e){return{resizeToContent:function(){this._layoutRect.autoResize=!0,this._lastRect=null,this.reflow()},resizeTo:function(t,n){if(1>=t||1>=n){var r=e.getWindowSize();t=1>=t?t*r.w:t,n=1>=n?n*r.h:n}return this._layoutRect.autoResize=!1,this.layoutRect({minW:t,minH:n,w:t,h:n}).reflow()},resizeBy:function(e,t){var n=this,r=n.layoutRect();return n.resizeTo(r.w+e,r.h+t)}}}),r(X,[K,G,Y,z],function(e,t,n,r){function i(e){var t;for(t=s.length;t--;)s[t]===e&&s.splice(t,1)}var o,a,s=[],l=[],c,u=e.extend({Mixins:[t,n],init:function(e){function t(){var e,t=u.zIndex||65535,n;if(l.length)for(e=0;e<l.length;e++)l[e].modal&&(t++,n=l[e]),l[e].getEl().style.zIndex=t,l[e].zIndex=t,t++;var i=document.getElementById(d.classPrefix+"modal-block");n?r.css(i,"z-index",n.zIndex-1):i&&(i.parentNode.removeChild(i),c=!1),u.currentZIndex=t}function n(e,t){for(;e;){if(e==t)return!0;e=e.parent()}}function i(e){function t(t,n){for(var r,i=0;i<s.length;i++)if(s[i]!=e)for(r=s[i].parent();r&&(r=r.parent());)r==e&&s[i].fixed(t).moveBy(0,n).repaint()}var n=r.getViewPort().y;e.settings.autofix&&(e._fixed?e._autoFixY>n&&(e.fixed(!1).layoutRect({y:e._autoFixY}).repaint(),t(!1,e._autoFixY-n)):(e._autoFixY=e.layoutRect().y,e._autoFixY<n&&(e.fixed(!0).layoutRect({y:0}).repaint(),t(!0,n-e._autoFixY))))}var d=this;d._super(e),d._eventsRoot=d,d.addClass("floatpanel"),e.autohide&&(o||(o=function(e){var t,r=d.getParentCtrl(e.target);for(t=s.length;t--;){var i=s[t];if(i.settings.autohide){if(r&&(n(r,i)||i.parent()===r))continue;e=i.fire("autohide",{target:e.target}),e.isDefaultPrevented()||i.hide()}}},r.on(document,"click",o)),s.push(d)),e.autofix&&(a||(a=function(){var e;for(e=s.length;e--;)i(s[e])},r.on(window,"scroll",a)),d.on("move",function(){i(this)})),d.on("postrender show",function(e){if(e.control==d){var n,i=d.classPrefix;d.modal&&!c&&(n=r.createFragment('<div id="'+i+'modal-block" class="'+i+"reset "+i+'fade"></div>'),n=n.firstChild,d.getContainerElm().appendChild(n),setTimeout(function(){r.addClass(n,i+"in"),r.addClass(d.getEl(),i+"in")},0),c=!0),l.push(d),t()}}),d.on("close hide",function(e){if(e.control==d){for(var n=l.length;n--;)l[n]===d&&l.splice(n,1);t()}}),d.on("show",function(){d.parents().each(function(e){return e._fixed?(d.fixed(!0),!1):void 0})}),e.popover&&(d._preBodyHtml='<div class="'+d.classPrefix+'arrow"></div>',d.addClass("popover").addClass("bottom").addClass("start"))},fixed:function(e){var t=this;if(t._fixed!=e){if(t._rendered){var n=r.getViewPort();e?t.layoutRect().y-=n.y:t.layoutRect().y+=n.y}t.toggleClass("fixed",e),t._fixed=e}return t},show:function(){var e=this,t,n=e._super();for(t=s.length;t--&&s[t]!==e;);return-1===t&&s.push(e),n},hide:function(){return i(this),this._super()},hideAll:function(){u.hideAll()},close:function(){var e=this;return e.fire("close"),e.remove()},remove:function(){i(this),this._super()}});return u.hideAll=function(){for(var e=s.length;e--;){var t=s[e];t.settings.autohide&&(t.fire("cancel",{},!1),t.hide(),s.splice(e,1))}},u}),r(J,[z],function(e){return function(t){function n(){if(!h)if(h=[],d.find)d.find("*").each(function(e){e.canFocus&&h.push(e.getEl())});else for(var e=d.getEl().getElementsByTagName("*"),t=0;t<e.length;t++)e[t].id&&e[t]&&h.push(e[t])}function r(){return document.getElementById(m)}function i(e){return e=e||r(),e&&e.getAttribute("role")}function o(e){for(var t,n=e||r();n=n.parentNode;)if(t=i(n))return t}function a(e){var t=document.getElementById(m);return t?t.getAttribute("aria-"+e):void 0}function s(){var n=r();if(!n||"TEXTAREA"!=n.nodeName&&"text"!=n.type)return t.onAction?t.onAction(m):e.fire(r(),"click",{keyboard:!0}),!0}function l(){var e;t.onCancel?((e=r())&&e.blur(),t.onCancel()):t.root.fire("cancel")}function c(e){function r(e){for(var t=d?d.getEl():document.body;e&&e!=t;){if("none"==e.style.display)return!1;e=e.parentNode}return!0}var i=-1,o,a,l=[];for(n(),a=l.length,a=0;a<h.length;a++)r(h[a])&&l.push(h[a]);for(a=l.length;a--;)if(l[a].id===m){i=a;break}i+=e,0>i?i=l.length-1:i>=l.length&&(i=0),o=l[i],o.focus(),m=o.id,t.actOnFocus&&s()}function u(){var e,r;for(r=i(t.root.getEl()),n(),e=h.length;e--;)if("toolbar"==r&&h[e].id===m)return h[e].focus(),void 0;h[0].focus()}var d=t.root,f=t.enableUpDown!==!1,p=t.enableLeftRight!==!1,h=t.items,m;return d.on("keydown",function(e){var n=37,r=39,u=38,d=40,h=27,m=14,g=13,v=32,y=9,b;switch(e.keyCode){case n:p&&(t.leftAction?t.leftAction():c(-1),b=!0);break;case r:p&&("menuitem"==i()&&"menu"==o()?a("haspopup")&&s():c(1),b=!0);break;case u:f&&(c(-1),b=!0);break;case d:f&&("menuitem"==i()&&"menubar"==o()?s():"button"==i()&&a("haspopup")?s():c(1),b=!0);break;case y:b=!0,e.shiftKey?c(-1):c(1);break;case h:b=!0,l();break;case m:case g:case v:b=s()}b&&(e.stopPropagation(),e.preventDefault())}),d.on("focusin",function(e){n(),m=e.target.id}),{moveFocus:c,focusFirst:u,cancel:l}}}),r(Q,[X,K,z,J,$],function(e,t,n,r,i){var o=e.extend({modal:!0,Defaults:{border:1,layout:"flex",containerCls:"panel",role:"dialog",callbacks:{submit:function(){this.fire("submit",{data:this.toJSON()})},close:function(){this.close()}}},init:function(e){var n=this;n._super(e),n.addClass("window"),n._fixed=!0,e.buttons&&(n.statusbar=new t({layout:"flex",border:"1 0 0 0",spacing:3,padding:10,align:"center",pack:"end",defaults:{type:"button"},items:e.buttons}),n.statusbar.addClass("foot"),n.statusbar.parent(n)),n.on("click",function(e){-1!=e.target.className.indexOf(n.classPrefix+"close")&&n.close()}),n.aria("label",e.title),n._fullscreen=!1},recalc:function(){var e=this,t=e.statusbar,r,i,o;e._fullscreen&&(e.layoutRect(n.getWindowSize()),e.layoutRect().contentH=e.layoutRect().innerH),e._super(),r=e.layoutRect(),e.settings.title&&!e._fullscreen&&(i=r.headerW,i>r.w&&(e.layoutRect({w:i}),o=!0)),t&&(t.layoutRect({w:e.layoutRect().innerW}).recalc(),i=t.layoutRect().minW+r.deltaW,i>r.w&&(e.layoutRect({w:i}),o=!0)),o&&e.recalc()},initLayoutRect:function(){var e=this,t=e._super(),r=0,i;e.settings.title&&!e._fullscreen&&(i=e.getEl("head"),t.headerW=i.offsetWidth,t.headerH=i.offsetHeight,r+=t.headerH),e.statusbar&&(r+=e.statusbar.layoutRect().h),t.deltaH+=r,t.minH+=r,t.h+=r;var o=n.getWindowSize();return t.x=Math.max(0,o.w/2-t.w/2),t.y=Math.max(0,o.h/2-t.h/2),t},renderHtml:function(){var e=this,t=e._layout,n=e._id,r=e.classPrefix,i=e.settings,o="",a="",s=i.html;return e.preRender(),t.preRender(e),i.title&&(o='<div id="'+n+'-head" class="'+r+'window-head">'+'<div class="'+r+'title">'+e.encode(i.title)+"</div>"+'<button type="button" class="'+r+'close" aria-hidden="true">×</button>'+'<div id="'+n+'-dragh" class="'+r+'dragh"></div>'+"</div>"),i.url&&(s='<iframe src="'+i.url+'" tabindex="-1"></iframe>'),"undefined"==typeof s&&(s=t.renderHtml(e)),e.statusbar&&(a=e.statusbar.renderHtml()),'<div id="'+n+'" class="'+e.classes()+'" hideFocus="1" tabIndex="-1">'+o+'<div id="'+n+'-body" class="'+e.classes("body")+'">'+s+"</div>"+a+"</div>"},fullscreen:function(e){var t=this,r=document.documentElement,i,o=t.classPrefix,a;if(e!=t._fullscreen)if(n.on(window,"resize",function(){var e;if(t._fullscreen)if(i)t._timer||(t._timer=setTimeout(function(){var e=n.getWindowSize();t.moveTo(0,0).resizeTo(e.w,e.h),t._timer=0},50));else{e=(new Date).getTime();var r=n.getWindowSize();t.moveTo(0,0).resizeTo(r.w,r.h),(new Date).getTime()-e>50&&(i=!0)}}),a=t.layoutRect(),t._fullscreen=e,e){t._initial={x:a.x,y:a.y,w:a.w,h:a.h},t._borderBox=t.parseBox("0"),t.getEl("head").style.display="none",a.deltaH-=a.headerH+2,n.addClass(r,o+"fullscreen"),n.addClass(document.body,o+"fullscreen"),t.addClass("fullscreen");var s=n.getWindowSize();t.moveTo(0,0).resizeTo(s.w,s.h)}else t._borderBox=t.parseBox(t.settings.border),t.getEl("head").style.display="",a.deltaH+=a.headerH,n.removeClass(r,o+"fullscreen"),n.removeClass(document.body,o+"fullscreen"),t.removeClass("fullscreen"),t.moveTo(t._initial.x,t._initial.y).resizeTo(t._initial.w,t._initial.h);return t.reflow()},postRender:function(){var e=this,t=[],n,o,a;setTimeout(function(){e.addClass("in")},0),e.keyboardNavigation=new r({root:e,enableLeftRight:!1,enableUpDown:!1,items:t,onCancel:function(){e.close()}}),e.find("*").each(function(e){e.canFocus&&(o=o||e.settings.autofocus,n=n||e,"filepicker"==e.type?(t.push(e.getEl("inp")),e.getEl("open")&&t.push(e.getEl("open").firstChild)):t.push(e.getEl()))}),e.statusbar&&e.statusbar.find("*").each(function(e){e.canFocus&&(o=o||e.settings.autofocus,n=n||e,t.push(e.getEl()))}),e._super(),e.statusbar&&e.statusbar.postRender(),!o&&n&&n.focus(),this.dragHelper=new i(e._id+"-dragh",{start:function(){a={x:e.layoutRect().x,y:e.layoutRect().y}},drag:function(t){e.moveTo(a.x+t.deltaX,a.y+t.deltaY)}}),e.on("submit",function(t){t.isDefaultPrevented()||e.close()})},submit:function(){var e=this.getParentCtrl(document.activeElement);return e&&e.blur(),this.fire("submit",{data:this.toJSON()})},remove:function(){var e=this;e._super(),e.dragHelper.destroy(),e.statusbar&&this.statusbar.remove()}});return o}),r(Z,[Q],function(e){var t=e.extend({init:function(e){e={border:1,padding:20,layout:"flex",pack:"center",align:"center",containerCls:"panel",autoScroll:!0,buttons:{type:"button",text:"Ok",action:"ok"},items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200}},this._super(e)},Statics:{OK:1,OK_CANCEL:2,YES_NO:3,YES_NO_CANCEL:4,msgBox:function(n){var r,i=n.callback||function(){};switch(n.buttons){case t.OK_CANCEL:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close(),i(!0)}},{type:"button",text:"Cancel",onClick:function(e){e.control.parents()[1].close(),i(!1)}}];break;case t.YES_NO:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close(),i(!0)}}];break;case t.YES_NO_CANCEL:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close()}}];break;default:r=[{type:"button",text:"Ok",subtype:"primary",onClick:function(e){e.control.parents()[1].close()}}]}return new e({padding:20,x:n.x,y:n.y,minWidth:300,minHeight:100,layout:"flex",pack:"center",align:"center",buttons:r,title:n.title,items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200,text:n.text},onClose:n.onClose}).renderTo(document.body).reflow()},alert:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,t.msgBox(e)},confirm:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,e.buttons=t.OK_CANCEL,t.msgBox(e)}}});return t}),r(et,[Q,Z],function(e,t){return function(n){var r=this,i=[];r.windows=i,r.open=function(t,r){var o;return t.url=t.url||t.file,t.url&&(t.width=parseInt(t.width||320,10),t.height=parseInt(t.height||240,10)),t.body&&(t.items={defaults:t.defaults,type:t.bodyType||"form",items:t.body}),t.url||t.buttons||(t.buttons=[{text:"Ok",subtype:"primary",onclick:function(){o.find("form")[0].submit(),o.close()}},{text:"Cancel",onclick:function(){o.close()}}]),o=new e(t),i.push(o),o.on("close",function(){for(var e=i.length;e--;)i[e]===o&&i.splice(e,1);n.focus()}),t.data&&o.on("postRender",function(){this.find("*").each(function(e){var n=e.name();n in t.data&&e.value(t.data[n])})}),o.params=r||{},n.nodeChanged(),o.renderTo(document.body).reflow()},r.alert=function(e,n,r){t.alert(e,function(){n.call(r||this)})},r.confirm=function(e,n,r){t.confirm(e,function(e){n.call(r||this,e)})},r.close=function(){i.length&&i[i.length-1].close()},r.getParams=function(){return i.length?i[i.length-1].params:null},r.setParams=function(e){i.length&&(i[i.length-1].params=e)}}}),r(tt,[T,B,C,m,g,p],function(e,t,n,r,i,o){return function(a){function s(e,t){try{a.getDoc().execCommand(e,!1,t)}catch(n){}}function l(){var e=a.getDoc().documentMode;return e?e:6}function c(e){return e.isDefaultPrevented()}function u(){function t(e){function t(){if(3==l.nodeType){if(e&&c==l.length)return!0;if(!e&&0===c)return!0}}var n,r,i,s,l,c,u;n=F.getRng();var d=[n.startContainer,n.startOffset,n.endContainer,n.endOffset];if(n.collapsed||(e=!0),l=n[(e?"start":"end")+"Container"],c=n[(e?"start":"end")+"Offset"],3==l.nodeType&&(r=I.getParent(n.startContainer,I.isBlock),e&&(r=I.getNext(r,I.isBlock)),!r||!t()&&n.collapsed||(i=I.create("em",{id:"__mceDel"}),H(o.grep(r.childNodes),function(e){i.appendChild(e)}),r.appendChild(i))),n=I.createRng(),n.setStart(d[0],d[1]),n.setEnd(d[2],d[3]),F.setRng(n),a.getDoc().execCommand(e?"ForwardDelete":"Delete",!1,null),i){for(s=F.getBookmark();u=I.get("__mceDel");)I.remove(u,!0); +F.moveToBookmark(s)}}a.on("keydown",function(n){var r;r=n.keyCode==O,c(n)||!r&&n.keyCode!=P||e.modifierPressed(n)||(n.preventDefault(),t(r))}),a.addCommand("Delete",function(){t()})}function d(){function e(e){var t=I.create("body"),n=e.cloneContents();return t.appendChild(n),F.serializer.serialize(t,{format:"html"})}function t(t){var n=e(t),r=I.createRng();r.selectNode(a.getBody());var i=e(r);return n===i}a.on("keydown",function(e){var n=e.keyCode,r;if(!c(e)&&(n==O||n==P)){if(r=a.selection.isCollapsed(),r&&!I.isEmpty(a.getBody()))return;if(q&&!r)return;if(!r&&!t(a.selection.getRng()))return;e.preventDefault(),a.setContent(""),a.selection.setCursorLocation(a.getBody(),0),a.nodeChanged()}})}function f(){a.on("keydown",function(t){!c(t)&&65==t.keyCode&&e.metaKeyPressed(t)&&(t.preventDefault(),a.execCommand("SelectAll"))})}function p(){a.settings.content_editable||(I.bind(a.getDoc(),"focusin",function(){F.setRng(F.getRng())}),I.bind(a.getDoc(),"mousedown",function(e){e.target==a.getDoc().documentElement&&(a.getWin().focus(),F.setRng(F.getRng()))}))}function h(){a.on("keydown",function(e){if(!c(e)&&e.keyCode===P&&F.isCollapsed()&&0===F.getRng(!0).startOffset){var t=F.getNode(),n=t.previousSibling;n&&n.nodeName&&"hr"===n.nodeName.toLowerCase()&&(I.remove(n),e.preventDefault())}})}function m(){window.Range.prototype.getClientRects||a.on("mousedown",function(e){if(!c(e)&&"HTML"===e.target.nodeName){var t=a.getBody();t.blur(),setTimeout(function(){t.focus()},0)}})}function g(){a.on("click",function(e){e=e.target,/^(IMG|HR)$/.test(e.nodeName)&&F.getSel().setBaseAndExtent(e,0,e,1),"A"==e.nodeName&&I.hasClass(e,"mce-item-anchor")&&F.select(e),a.nodeChanged()})}function v(){function e(){var e=I.getAttribs(F.getStart().cloneNode(!1));return function(){var t=F.getStart();t!==a.getBody()&&(I.setAttrib(t,"style",null),H(e,function(e){t.setAttributeNode(e.cloneNode(!0))}))}}function t(){return!F.isCollapsed()&&I.getParent(F.getStart(),I.isBlock)!=I.getParent(F.getEnd(),I.isBlock)}a.on("keypress",function(n){var r;return c(n)||8!=n.keyCode&&46!=n.keyCode||!t()?void 0:(r=e(),a.getDoc().execCommand("delete",!1,null),r(),n.preventDefault(),!1)}),I.bind(a.getDoc(),"cut",function(n){var r;!c(n)&&t()&&(r=e(),setTimeout(function(){r()},0))})}function y(){var e,n;a.on("selectionchange",function(){n&&(clearTimeout(n),n=0),n=window.setTimeout(function(){var n=F.getRng();e&&t.compareRanges(n,e)||(a.nodeChanged(),e=n)},50)})}function b(){document.body.setAttribute("role","application")}function C(){a.on("keydown",function(e){if(!c(e)&&e.keyCode===P&&F.isCollapsed()&&0===F.getRng(!0).startOffset){var t=F.getNode().previousSibling;if(t&&t.nodeName&&"table"===t.nodeName.toLowerCase())return e.preventDefault(),!1}})}function x(){l()>7||(s("RespectVisibilityInDesign",!0),a.contentStyles.push(".mceHideBrInPre pre br {display: none}"),I.addClass(a.getBody(),"mceHideBrInPre"),z.addNodeFilter("pre",function(e){for(var t=e.length,r,i,o,a;t--;)for(r=e[t].getAll("br"),i=r.length;i--;)o=r[i],a=o.prev,a&&3===a.type&&"\n"!=a.value.charAt(a.value-1)?a.value+="\n":o.parent.insert(new n("#text",3),o,!0).value="\n"}),V.addNodeFilter("pre",function(e){for(var t=e.length,n,r,i,o;t--;)for(n=e[t].getAll("br"),r=n.length;r--;)i=n[r],o=i.prev,o&&3==o.type&&(o.value=o.value.replace(/\r?\n$/,""))}))}function w(){I.bind(a.getBody(),"mouseup",function(){var e,t=F.getNode();"IMG"==t.nodeName&&((e=I.getStyle(t,"width"))&&(I.setAttrib(t,"width",e.replace(/[^0-9%]+/g,"")),I.setStyle(t,"width","")),(e=I.getStyle(t,"height"))&&(I.setAttrib(t,"height",e.replace(/[^0-9%]+/g,"")),I.setStyle(t,"height","")))})}function _(){a.on("keydown",function(t){var n,r,i,o,s,l,u,d;if(n=t.keyCode==O,!c(t)&&(n||t.keyCode==P)&&!e.modifierPressed(t)&&(r=F.getRng(),i=r.startContainer,o=r.startOffset,u=r.collapsed,3==i.nodeType&&i.nodeValue.length>0&&(0===o&&!u||u&&o===(n?0:1)))){if(l=i.previousSibling,l&&"IMG"==l.nodeName)return;d=a.schema.getNonEmptyElements(),t.preventDefault(),s=I.create("br",{id:"__tmp"}),i.parentNode.insertBefore(s,i),a.getDoc().execCommand(n?"ForwardDelete":"Delete",!1,null),i=F.getRng().startContainer,l=i.previousSibling,l&&1==l.nodeType&&!I.isBlock(l)&&I.isEmpty(l)&&!d[l.nodeName.toLowerCase()]&&I.remove(l),I.remove("__tmp")}})}function N(){a.on("keydown",function(t){var n,r,i,o,s;if(!c(t)&&t.keyCode==e.BACKSPACE&&(n=F.getRng(),r=n.startContainer,i=n.startOffset,o=I.getRoot(),s=r,n.collapsed&&0===i)){for(;s&&s.parentNode&&s.parentNode.firstChild==s&&s.parentNode!=o;)s=s.parentNode;"BLOCKQUOTE"===s.tagName&&(a.formatter.toggle("blockquote",null,s),n=I.createRng(),n.setStart(r,0),n.setEnd(r,0),F.setRng(n))}})}function E(){function e(){a._refreshContentEditable(),s("StyleWithCSS",!1),s("enableInlineTableEditing",!1),W.object_resizing||s("enableObjectResizing",!1)}W.readonly||a.on("BeforeExecCommand MouseDown",e)}function S(){function e(){H(I.select("a"),function(e){var t=e.parentNode,n=I.getRoot();if(t.lastChild===e){for(;t&&!I.isBlock(t);){if(t.parentNode.lastChild!==t||t===n)return;t=t.parentNode}I.add(t,"br",{"data-mce-bogus":1})}})}a.on("SetContent ExecCommand",function(t){("setcontent"==t.type||"mceInsertLink"===t.command)&&e()})}function k(){W.forced_root_block&&a.on("init",function(){s("DefaultParagraphSeparator",W.forced_root_block)})}function T(){a.on("Undo Redo SetContent",function(e){e.initial||a.execCommand("mceRepaint")})}function R(){a.on("keydown",function(e){var t;c(e)||e.keyCode!=P||(t=a.getDoc().selection.createRange(),t&&t.item&&(e.preventDefault(),a.undoManager.beforeChange(),I.remove(t.item(0)),a.undoManager.add()))})}function A(){var e;l()>=10&&(e="",H("p div h1 h2 h3 h4 h5 h6".split(" "),function(t,n){e+=(n>0?",":"")+t+":empty"}),a.contentStyles.push(e+"{padding-right: 1px !important}"))}function B(){l()<9&&(z.addNodeFilter("noscript",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.firstChild,r&&n.attr("data-mce-innertext",r.value)}),V.addNodeFilter("noscript",function(e){for(var t=e.length,i,o,a;t--;)i=e[t],o=e[t].firstChild,o?o.value=r.decode(o.value):(a=i.attributes.map["data-mce-innertext"],a&&(i.attr("data-mce-innertext",null),o=new n("#text",3),o.value=a,o.raw=!0,i.append(o)))}))}function L(){function e(e,t){var n=i.createTextRange();try{n.moveToPoint(e,t)}catch(r){n=null}return n}function t(t){var r;t.button?(r=e(t.x,t.y),r&&(r.compareEndPoints("StartToStart",a)>0?r.setEndPoint("StartToStart",a):r.setEndPoint("EndToEnd",a),r.select())):n()}function n(){var e=r.selection.createRange();a&&!e.item&&0===e.compareEndPoints("StartToEnd",e)&&a.select(),I.unbind(r,"mouseup",n),I.unbind(r,"mousemove",t),a=o=0}var r=I.doc,i=r.body,o,a,s;r.documentElement.unselectable=!0,I.bind(r,"mousedown contextmenu",function(i){if("HTML"===i.target.nodeName){if(o&&n(),s=r.documentElement,s.scrollHeight>s.clientHeight)return;o=1,a=e(i.x,i.y),a&&(I.bind(r,"mouseup",n),I.bind(r,"mousemove",t),I.win.focus(),a.select())}})}function M(){a.on("keyup focusin",function(t){65==t.keyCode&&e.metaKeyPressed(t)||F.normalize()})}function D(){a.contentStyles.push("img:-moz-broken {-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}")}var H=o.each,P=e.BACKSPACE,O=e.DELETE,I=a.dom,F=a.selection,W=a.settings,z=a.parser,V=a.serializer,U=i.gecko,q=i.ie,$=i.webkit;C(),N(),d(),M(),$&&(_(),u(),p(),g(),k(),i.iOS?y():f()),q&&(h(),b(),x(),w(),R(),A(),B(),L()),U&&(h(),m(),v(),E(),S(),T(),D())}}),r(nt,[p],function(e){function t(){return!1}function n(){return!0}var r="__bindings",i=e.makeMap("focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange mouseout mouseenter mouseleave keydown keypress keyup contextmenu dragend dragover draggesture dragdrop drop drag"," ");return{fire:function(e,i,o){var a=this,s,l,c,u,d;if(e=e.toLowerCase(),i=i||{},i.type=e,i.target||(i.target=a),i.preventDefault||(i.preventDefault=function(){i.isDefaultPrevented=n},i.stopPropagation=function(){i.isPropagationStopped=n},i.stopImmediatePropagation=function(){i.isImmediatePropagationStopped=n},i.isDefaultPrevented=t,i.isPropagationStopped=t,i.isImmediatePropagationStopped=t),a[r]&&(s=a[r][e]))for(l=0,c=s.length;c>l&&(s[l]=u=s[l],!i.isImmediatePropagationStopped());l++)if(u.call(a,i)===!1)return i.preventDefault(),i;if(o!==!1&&a.parent)for(d=a.parent();d&&!i.isPropagationStopped();)d.fire(e,i,!1),d=d.parent();return i},on:function(e,t){var n=this,o,a,s,l;if(t===!1&&(t=function(){return!1}),t)for(s=e.toLowerCase().split(" "),l=s.length;l--;)e=s[l],o=n[r],o||(o=n[r]={}),a=o[e],a||(a=o[e]=[],n.bindNative&&i[e]&&n.bindNative(e)),a.push(t);return n},off:function(e,t){var n=this,o,a=n[r],s,l,c,u;if(a)if(e)for(c=e.toLowerCase().split(" "),o=c.length;o--;){if(e=c[o],s=a[e],!e){for(l in a)a[e].length=0;return n}if(s){if(t)for(u=s.length;u--;)s[u]===t&&s.splice(u,1);else s.length=0;!s.length&&n.unbindNative&&i[e]&&(n.unbindNative(e),delete a[e])}}else{if(n.unbindNative)for(e in a)n.unbindNative(e);n[r]=[]}return n}}}),r(rt,[p,g],function(e,t){var n=e.each,r=e.explode,i={f9:120,f10:121,f11:122};return function(o){var a=this,s={};o.on("keyup keypress keydown",function(e){(e.altKey||e.ctrlKey||e.metaKey)&&n(s,function(n){var r=t.mac?e.ctrlKey||e.metaKey:e.ctrlKey;if(n.ctrl==r&&n.alt==e.altKey&&n.shift==e.shiftKey)return e.keyCode==n.keyCode||e.charCode&&e.charCode==n.charCode?(e.preventDefault(),"keydown"==e.type&&n.func.call(n.scope),!0):void 0})}),a.add=function(t,a,l,c){var u;return u=l,"string"==typeof l?l=function(){o.execCommand(u,!1,null)}:e.isArray(u)&&(l=function(){o.execCommand(u[0],u[1],u[2])}),n(r(t.toLowerCase()),function(e){var t={func:l,scope:c||o,desc:o.translate(a),alt:!1,ctrl:!1,shift:!1};n(r(e,"+"),function(e){switch(e){case"alt":case"ctrl":case"shift":t[e]=!0;break;default:t.charCode=e.charCodeAt(0),t.keyCode=i[e]||e.toUpperCase().charCodeAt(0)}}),s[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t}),!0}}}),r(it,[v,b,C,S,E,A,L,M,D,H,P,O,y,l,et,x,_,tt,g,p,nt,rt],function(e,n,r,i,o,a,s,l,c,u,d,f,p,h,m,g,v,y,b,C,x,w){function _(e,t){return"selectionchange"==t||"drop"==t?e.getDoc():!e.inline&&/^mouse|click|contextmenu/.test(t)?e.getDoc():e.getBody()}function N(e,t,r){var i=this,o,a;o=i.documentBaseUrl=r.documentBaseURL,a=r.baseURI,i.settings=t=T({id:e,theme:"modern",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:o,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:"<!DOCTYPE html>",visual:!0,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",forced_root_block:"p",hidden_input:!0,padd_empty_editor:!0,render_ui:!0,indentation:"30px",inline_styles:!0,convert_fonts_to_spans:!0,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",validate:!0,entity_encoding:"named",url_converter:i.convertURL,url_converter_scope:i,ie7_compat:!0},t),n.settings=t,n.baseURL=r.baseURL,i.id=t.id=e,i.isNotDirty=!0,i.plugins={},i.documentBaseURI=new f(t.document_base_url||o,{base_uri:a}),i.baseURI=a,i.contentCSS=[],i.contentStyles=[],i.shortcuts=new w(i),i.execCommands={},i.queryStateCommands={},i.queryValueCommands={},i.loadedCSS={},i.suffix=r.suffix,i.editorManager=r,i.inline=t.inline,i.execCallback("setup",i)}var E=e.DOM,S=n.ThemeManager,k=n.PluginManager,T=C.extend,R=C.each,A=C.explode,B=C.inArray,L=C.trim,M=C.resolve,D=h.Event,H=b.gecko,P=b.ie,O=b.opera;return N.prototype={render:function(){function e(){var e=p.ScriptLoader;n.language&&"en"!=n.language&&(n.language_url=t.editorManager.baseURL+"/langs/"+n.language+".js"),n.language_url&&e.add(n.language_url),n.theme&&"function"!=typeof n.theme&&"-"!=n.theme.charAt(0)&&!S.urls[n.theme]&&S.load(n.theme,"themes/"+n.theme+"/theme"+i+".js"),C.isArray(n.plugins)&&(n.plugins=n.plugins.join(" ")),R(n.external_plugins,function(e,t){k.load(t,e),n.plugins+=" "+t}),R(n.plugins.split(/[ ,]/),function(e){if(e=L(e),e&&!k.urls[e])if("-"==e.charAt(0)){e=e.substr(1,e.length);var t=k.dependencies(e);R(t,function(e){var t={prefix:"plugins/",resource:e,suffix:"/plugin"+i+".js"};e=k.createUrl(t,e),k.load(e.resource,e)})}else k.load(e,{prefix:"plugins/",resource:e,suffix:"/plugin"+i+".js"})}),e.loadQueue(function(){t.removed||t.init()})}var t=this,n=t.settings,r=t.id,i=t.suffix;if(!D.domLoaded)return E.bind(window,"ready",function(){t.render()}),void 0;if(t.editorManager.settings=n,t.getElement()&&b.contentEditable){n.inline?t.inline=!0:(t.orgVisibility=t.getElement().style.visibility,t.getElement().style.visibility="hidden");var o=t.getElement().form||E.getParent(r,"form");o&&(t.formElement=o,n.hidden_input&&!/TEXTAREA|INPUT/i.test(t.getElement().nodeName)&&E.insertAfter(E.create("input",{type:"hidden",name:r}),r),t.formEventDelegate=function(e){t.fire(e.type,e)},E.bind(o,"submit reset",t.formEventDelegate),t.on("reset",function(){t.setContent(t.startContent,{format:"raw"})}),!n.submit_patch||o.submit.nodeType||o.submit.length||o._mceOldSubmit||(o._mceOldSubmit=o.submit,o.submit=function(){return t.editorManager.triggerSave(),t.isNotDirty=!0,o._mceOldSubmit(o)})),t.windowManager=new m(t),"xml"==n.encoding&&t.on("GetContent",function(e){e.save&&(e.content=E.encode(e.content))}),n.add_form_submit_trigger&&t.on("submit",function(){t.initialized&&(t.save(),t.isNotDirty=!0)}),n.add_unload_trigger&&(t._beforeUnload=function(){!t.initialized||t.destroyed||t.isHidden()||t.save({format:"raw",no_events:!0})},t.editorManager.on("BeforeUnload",t._beforeUnload)),e()}},init:function(){function e(n){var r=k.get(n),i,o;i=k.urls[n]||t.documentBaseUrl.replace(/\/$/,""),n=L(n),r&&-1===B(h,n)&&(R(k.dependencies(n),function(t){e(t)}),o=new r(t,i),t.plugins[n]=o,o.init&&(o.init(t,i),h.push(n)))}var t=this,n=t.settings,r=t.getElement(),i,o,a,s,l,c,u,d,f,p,h=[];if(t.editorManager.add(t),n.aria_label=n.aria_label||E.getAttrib(r,"aria-label",t.getLang("aria.rich_text_area")),n.theme&&("function"!=typeof n.theme?(n.theme=n.theme.replace(/-/,""),l=S.get(n.theme),t.theme=new l(t,S.urls[n.theme]),t.theme.init&&t.theme.init(t,S.urls[n.theme]||t.documentBaseUrl.replace(/\/$/,""))):t.theme=n.theme),R(n.plugins.replace(/\-/g,"").split(/[ ,]/),e),t.fire("BeforeRenderUI"),n.render_ui&&t.theme&&(t.orgDisplay=r.style.display,"function"!=typeof n.theme?(i=n.width||r.style.width||r.offsetWidth,o=n.height||r.style.height||r.offsetHeight,a=n.min_height||100,f=/^[0-9\.]+(|px)$/i,f.test(""+i)&&(i=Math.max(parseInt(i,10)+(l.deltaWidth||0),100)),f.test(""+o)&&(o=Math.max(parseInt(o,10)+(l.deltaHeight||0),a)),l=t.theme.renderUI({targetNode:r,width:i,height:o,deltaWidth:n.delta_width,deltaHeight:n.delta_height}),n.content_editable||(E.setStyles(l.sizeContainer||l.editorContainer,{wi2dth:i,h2eight:o}),o=(l.iframeHeight||o)+("number"==typeof o?l.deltaHeight||0:""),a>o&&(o=a))):(l=n.theme(t,r),l.editorContainer.nodeType&&(l.editorContainer=l.editorContainer.id=l.editorContainer.id||t.id+"_parent"),l.iframeContainer.nodeType&&(l.iframeContainer=l.iframeContainer.id=l.iframeContainer.id||t.id+"_iframecontainer"),o=l.iframeHeight||r.offsetHeight),t.editorContainer=l.editorContainer),n.content_css&&R(A(n.content_css),function(e){t.contentCSS.push(t.documentBaseURI.toAbsolute(e))}),n.content_style&&t.contentStyles.push(n.content_style),n.content_editable)return r=s=l=null,t.initContentBody();for(document.domain&&location.hostname!=document.domain&&(t.editorManager.relaxedDomain=document.domain),t.iframeHTML=n.doctype+"<html><head>",n.document_base_url!=t.documentBaseUrl&&(t.iframeHTML+='<base href="'+t.documentBaseURI.getURI()+'" />'),!b.caretAfter&&n.ie7_compat&&(t.iframeHTML+='<meta http-equiv="X-UA-Compatible" content="IE=7" />'),t.iframeHTML+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />',p=0;p<t.contentCSS.length;p++){var m=t.contentCSS[p];t.iframeHTML+='<link type="text/css" rel="stylesheet" href="'+m+'" />',t.loadedCSS[m]=!0}u=n.body_id||"tinymce",-1!=u.indexOf("=")&&(u=t.getParam("body_id","","hash"),u=u[t.id]||u),d=n.body_class||"",-1!=d.indexOf("=")&&(d=t.getParam("body_class","","hash"),d=d[t.id]||""),t.iframeHTML+='</head><body id="'+u+'" class="mce-content-body '+d+'" '+"onload=\"window.parent.tinymce.get('"+t.id+"').fire('load');\"><br></body></html>",t.editorManager.relaxedDomain&&(P||O&&parseFloat(window.opera.version())<11)&&(c='javascript:(function(){document.open();document.domain="'+document.domain+'";'+'var ed = window.parent.tinymce.get("'+t.id+'");document.write(ed.iframeHTML);'+"document.close();ed.initContentBody();})()"),s=E.add(l.iframeContainer,"iframe",{id:t.id+"_ifr",src:c||'javascript:""',frameBorder:"0",allowTransparency:"true",title:t.editorManager.translate("Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help"),style:{width:"100%",height:o,display:"block"}}),t.contentAreaContainer=l.iframeContainer,l.editorContainer&&(E.get(l.editorContainer).style.display=t.orgDisplay),E.get(t.id).style.display="none",E.setAttrib(t.id,"aria-hidden",!0),t.editorManager.relaxedDomain&&c||t.initContentBody(),r=s=l=null},initContentBody:function(){var t=this,n=t.settings,o=E.get(t.id),f=t.getDoc(),p,h;n.inline||(t.getElement().style.visibility=t.orgVisibility),P&&t.editorManager.relaxedDomain||n.content_editable||(f.open(),f.write(t.iframeHTML),f.close(),t.editorManager.relaxedDomain&&(f.domain=t.editorManager.relaxedDomain)),n.content_editable&&(t.on("remove",function(){var e=this.getBody();E.removeClass(e,"mce-content-body"),E.removeClass(e,"mce-edit-focus"),E.setAttrib(e,"tabIndex",null),E.setAttrib(e,"contentEditable",null)}),E.addClass(o,"mce-content-body"),o.tabIndex=-1,t.contentDocument=f=n.content_document||document,t.contentWindow=n.content_window||window,t.bodyElement=o,n.content_document=n.content_window=null,n.root_name=o.nodeName.toLowerCase()),p=t.getBody(),p.disabled=!0,n.readonly||(p.contentEditable=t.getParam("content_editable_state",!0)),p.disabled=!1,t.schema=new g(n),t.dom=new e(f,{keep_values:!0,url_converter:t.convertURL,url_converter_scope:t,hex_colors:n.force_hex_style_colors,class_filter:n.class_filter,update_styles:!0,root_element:n.content_editable?t.id:null,schema:t.schema,onSetAttrib:function(e){t.fire("SetAttrib",e)}}),t.parser=new v(n,t.schema),t.parser.addAttributeFilter("src,href,style",function(e,n){for(var r=e.length,i,o=t.dom,a,s;r--;)i=e[r],a=i.attr(n),s="data-mce-"+n,i.attributes.map[s]||("style"===n?i.attr(s,o.serializeStyle(o.parseStyle(a),i.name)):i.attr(s,t.convertURL(a,n,i.name)))}),t.parser.addNodeFilter("script",function(e){for(var t=e.length,n;t--;)n=e[t],n.attr("type","mce-"+(n.attr("type")||"text/javascript"))}),t.parser.addNodeFilter("#cdata",function(e){for(var t=e.length,n;t--;)n=e[t],n.type=8,n.name="#comment",n.value="[CDATA["+n.value+"]]"}),t.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(e){for(var n=e.length,i,o=t.schema.getNonEmptyElements();n--;)i=e[n],i.isEmpty(o)&&(i.empty().append(new r("br",1)).shortEnded=!0)}),t.serializer=new i(n,t),t.selection=new a(t.dom,t.getWin(),t.serializer,t),t.formatter=new s(t),t.undoManager=new l(t),t.forceBlocks=new u(t),t.enterKey=new c(t),t.editorCommands=new d(t),t.fire("PreInit"),n.browser_spellcheck||n.gecko_spellcheck||(f.body.spellcheck=!1,E.setAttrib(p,"spellcheck","false")),t.fire("PostRender"),t.quirks=y(t),n.directionality&&(p.dir=n.directionality),n.nowrap&&(p.style.whiteSpace="nowrap"),n.protect&&t.on("BeforeSetContent",function(e){R(n.protect,function(t){e.content=e.content.replace(t,function(e){return"<!--mce:protected "+escape(e)+"-->"})})}),t.on("SetContent",function(){t.addVisual(t.getBody())}),n.padd_empty_editor&&t.on("PostProcess",function(e){e.content=e.content.replace(/^(<p[^>]*>( | |\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/,"")}),t.load({initial:!0,format:"html"}),t.startContent=t.getContent({format:"raw"}),t.initialized=!0,R(t._pendingNativeEvents,function(e){t.dom.bind(_(t,e),e,function(e){t.fire(e.type,e)})}),t.fire("init"),t.focus(!0),t.nodeChanged({initial:!0}),t.execCallback("init_instance_callback",t),t.contentStyles.length>0&&(h="",R(t.contentStyles,function(e){h+=e+"\r\n"}),t.dom.addStyle(h)),R(t.contentCSS,function(e){t.loadedCSS[e]||(t.dom.loadCSS(e),t.loadedCSS[e]=!0)}),n.auto_focus&&setTimeout(function(){var e=t.editorManager.get(n.auto_focus);e.selection.select(e.getBody(),1),e.selection.collapse(1),e.getBody().focus(),e.getWin().focus()},100),o=f=p=null},focus:function(e){var t,n=this,r=n.selection,i=n.settings.content_editable,o,a,s=n.getDoc(),l;e||(o=r.getRng(),o.item&&(a=o.item(0)),n._refreshContentEditable(),i||(b.opera||n.getBody().focus(),n.getWin().focus()),(H||i)&&(l=n.getBody(),l.setActive?l.setActive():l.focus(),i&&r.normalize()),a&&a.ownerDocument==s&&(o=s.body.createControlRange(),o.addElement(a),o.select())),n.editorManager.activeEditor!=n&&((t=n.editorManager.activeEditor)&&t.fire("deactivate",{relatedTarget:n}),n.fire("activate",{relatedTarget:t})),n.editorManager.activeEditor=n},execCallback:function(e){var t=this,n=t.settings[e],r;if(n)return t.callbackLookup&&(r=t.callbackLookup[e])&&(n=r.func,r=r.scope),"string"==typeof n&&(r=n.replace(/\.\w+$/,""),r=r?M(r):0,n=M(n),t.callbackLookup=t.callbackLookup||{},t.callbackLookup[e]={func:n,scope:r}),n.apply(r||t,Array.prototype.slice.call(arguments,1))},translate:function(e){var t=this.settings.language||"en",n=this.editorManager.i18n;return e?n[t+"."+e]||e.replace(/\{\#([^\}]+)\}/g,function(e,r){return n[t+"."+r]||"{#"+r+"}"}):""},getLang:function(e,n){return this.editorManager.i18n[(this.settings.language||"en")+"."+e]||(n!==t?n:"{#"+e+"}")},getParam:function(e,t,n){var r=e in this.settings?this.settings[e]:t,i;return"hash"===n?(i={},"string"==typeof r?R(r.indexOf("=")>0?r.split(/[;,](?![^=;,]*(?:[;,]|$))/):r.split(","),function(e){e=e.split("="),i[L(e[0])]=e.length>1?L(e[1]):L(e)}):i=r,i):r},nodeChanged:function(){var e=this,t=e.selection,n,r,i;e.initialized&&!e.settings.disable_nodechange&&(i=e.getBody(),n=t.getStart()||i,n=P&&n.ownerDocument!=e.getDoc()?e.getBody():n,"IMG"==n.nodeName&&t.isCollapsed()&&(n=n.parentNode),r=[],e.dom.getParent(n,function(e){return e===i?!0:(r.push(e),void 0)}),e.fire("NodeChange",{element:n,parents:r}))},addButton:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),t.text||t.icon||(t.icon=e),n.buttons=n.buttons||{},t.tooltip=t.tooltip||t.title,n.buttons[e]=t},addMenuItem:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),n.menuItems=n.menuItems||{},n.menuItems[e]=t},addCommand:function(e,t,n){this.execCommands[e]={func:t,scope:n||this}},addQueryStateHandler:function(e,t,n){this.queryStateCommands[e]={func:t,scope:n||this}},addQueryValueHandler:function(e,t,n){this.queryValueCommands[e]={func:t,scope:n||this}},addShortcut:function(e,t,n,r){this.shortcuts.add(e,t,n,r)},execCommand:function(e,t,n,r){var i=this,o=0,a;return/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(e)||r&&r.skip_focus||i.focus(),r=T({},r),r=i.fire("BeforeExecCommand",{command:e,ui:t,value:n}),r.isDefaultPrevented()?!1:(a=i.execCommands[e])&&a.func.call(a.scope,t,n)!==!0?(i.fire("ExecCommand",{command:e,ui:t,value:n}),!0):(R(i.plugins,function(r){return r.execCommand&&r.execCommand(e,t,n)?(i.fire("ExecCommand",{command:e,ui:t,value:n}),o=!0,!1):void 0}),o?o:i.theme&&i.theme.execCommand&&i.theme.execCommand(e,t,n)?(i.fire("ExecCommand",{command:e,ui:t,value:n}),!0):i.editorCommands.execCommand(e,t,n)?(i.fire("ExecCommand",{command:e,ui:t,value:n}),!0):(i.getDoc().execCommand(e,t,n),i.fire("ExecCommand",{command:e,ui:t,value:n}),void 0))},queryCommandState:function(e){var t=this,n,r;if(!t._isHidden()){if((n=t.queryStateCommands[e])&&(r=n.func.call(n.scope),r!==!0))return r;if(r=t.editorCommands.queryCommandState(e),-1!==r)return r;try{return t.getDoc().queryCommandState(e)}catch(i){}}},queryCommandValue:function(e){var n=this,r,i;if(!n._isHidden()){if((r=n.queryValueCommands[e])&&(i=r.func.call(r.scope),i!==!0))return i;if(i=n.editorCommands.queryCommandValue(e),i!==t)return i;try{return n.getDoc().queryCommandValue(e)}catch(o){}}},show:function(){var e=this;E.show(e.getContainer()),E.hide(e.id),e.load(),e.fire("show")},hide:function(){var e=this,t=e.getDoc();P&&t&&t.execCommand("SelectAll"),e.save(),E.hide(e.getContainer()),E.setStyle(e.id,"display",e.orgDisplay),e.fire("hide")},isHidden:function(){return!E.isHidden(this.id)},setProgressState:function(e,t){this.fire("ProgressState",{state:e,time:t})},load:function(e){var n=this,r=n.getElement(),i;return r?(e=e||{},e.load=!0,i=n.setContent(r.value!==t?r.value:r.innerHTML,e),e.element=r,e.no_events||n.fire("LoadContent",e),e.element=r=null,i):void 0},save:function(e){var t=this,n=t.getElement(),r,i;if(n&&t.initialized)return e=e||{},e.save=!0,e.element=n,r=e.content=t.getContent(e),e.no_events||t.fire("SaveContent",e),r=e.content,/TEXTAREA|INPUT/i.test(n.nodeName)?n.value=r:(n.innerHTML=r,(i=E.getParent(t.id,"form"))&&R(i.elements,function(e){return e.name==t.id?(e.value=r,!1):void 0})),e.element=n=null,t.isNotDirty=!0,r},setContent:function(e,t){var n=this,r=n.getBody(),i;return t=t||{},t.format=t.format||"html",t.set=!0,t.content=e,t.no_events||n.fire("BeforeSetContent",t),e=t.content,P||0!==e.length&&!/^\s+$/.test(e)?("raw"!==t.format&&(e=new o({},n.schema).serialize(n.parser.parse(e,{isRootContent:!0}))),t.content=L(e),n.dom.setHTML(r,t.content),t.no_events||n.fire("SetContent",t),n.settings.content_editable&&document.activeElement!==n.getBody()||n.selection.normalize(),t.content):(i=n.settings.forced_root_block,e=i&&n.schema.isValidChild(r.nodeName.toLowerCase(),i.toLowerCase())?"<"+i+'><br data-mce-bogus="1"></'+i+">":'<br data-mce-bogus="1">',r.innerHTML=e,n.selection.select(r,!0),n.selection.collapse(!0),n.fire("SetContent",t),void 0)},getContent:function(e){var t=this,n,r=t.getBody();return e=e||{},e.format=e.format||"html",e.get=!0,e.getInner=!0,e.no_events||t.fire("BeforeGetContent",e),n="raw"==e.format?r.innerHTML:"text"==e.format?r.innerText||r.textContent:t.serializer.serialize(r,e),e.content="text"!=e.format?L(n):n,e.no_events||t.fire("GetContent",e),e.content},insertContent:function(e){this.execCommand("mceInsertContent",!1,e)},isDirty:function(){return!this.isNotDirty},getContainer:function(){var e=this;return e.container||(e.container=E.get(e.editorContainer||e.id+"_parent")),e.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return E.get(this.settings.content_element||this.id)},getWin:function(){var e=this,t;return e.contentWindow||(t=E.get(e.id+"_ifr"),t&&(e.contentWindow=t.contentWindow)),e.contentWindow},getDoc:function(){var e=this,t;return e.contentDocument||(t=e.getWin(),t&&(e.contentDocument=t.document)),e.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(e,t,n){var r=this,i=r.settings;return i.urlconverter_callback?r.execCallback("urlconverter_callback",e,n,!0,t):!i.convert_urls||n&&"LINK"==n.nodeName||0===e.indexOf("file:")||0===e.length?e:i.relative_urls?r.documentBaseURI.toRelative(e):e=r.documentBaseURI.toAbsolute(e,i.remove_script_host)},addVisual:function(e){var n=this,r=n.settings,i=n.dom,o;e=e||n.getBody(),n.hasVisual===t&&(n.hasVisual=r.visual),R(i.select("table,a",e),function(e){var t;switch(e.nodeName){case"TABLE":return o=r.visual_table_class||"mce-item-table",t=i.getAttrib(e,"border"),t&&"0"!=t||(n.hasVisual?i.addClass(e,o):i.removeClass(e,o)),void 0;case"A":return i.getAttrib(e,"href",!1)||(t=i.getAttrib(e,"name")||e.id,o="mce-item-anchor",t&&(n.hasVisual?i.addClass(e,o):i.removeClass(e,o))),void 0}}),n.fire("VisualAid",{element:e,hasVisual:n.hasVisual})},remove:function(){var e=this,t=e.getContainer(),n=e.getDoc();e.removed||(e.removed=1,P&&n&&n.execCommand("SelectAll"),e.save(),E.setStyle(e.id,"display",e.orgDisplay),e.settings.content_editable||(D.unbind(e.getWin()),D.unbind(e.getDoc())),D.unbind(e.getBody()),D.unbind(t),e.fire("remove"),e.editorManager.remove(e),E.remove(t))},bindNative:function(e){var t=this;t.initialized?t.dom.bind(_(t,e),e,function(n){t.fire(e,n)}):t._pendingNativeEvents?t._pendingNativeEvents.push(e):t._pendingNativeEvents=[e]},unbindNative:function(e){var t=this;t.initialized&&t.dom.unbind(e)},destroy:function(e){var t=this,n;t.destroyed||(H&&(D.unbind(t.getDoc()),D.unbind(t.getWin()),D.unbind(t.getBody())),e||(t.editorManager.off("beforeunload",t._beforeUnload),t.theme&&t.theme.destroy&&t.theme.destroy(),t.selection.destroy(),t.dom.destroy()),n=t.formElement,n&&(n.submit=n._mceOldSubmit,n._mceOldSubmit=null,E.unbind(n,"submit reset",t.formEventDelegate)),t.contentAreaContainer=t.formElement=t.container=null,t.settings.content_element=t.bodyElement=t.contentDocument=t.contentWindow=null,t.selection&&(t.selection=t.selection.win=t.selection.dom=t.selection.dom.doc=null),t.destroyed=1)},_refreshContentEditable:function(){var e=this,t,n;e._isHidden()&&(t=e.getBody(),n=t.parentNode,n.removeChild(t),n.appendChild(t),t.focus())},_isHidden:function(){var e;return H?(e=this.selection.getSel(),!e||!e.rangeCount||0===e.rangeCount):0}},T(N.prototype,x),N}),r(ot,[],function(){var e={};return{add:function(t,n){for(var r in n)e[r]=n[r]},translate:function(t){if("undefined"==typeof t)return t;if("string"!=typeof t&&t.raw)return t.raw;if(t.push){var n=t.slice(1);t=(e[t[0]]||t[0]).replace(/\{([^\}]+)\}/g,function(e,t){return n[t]})}return e[t]||t},data:e}}),r(at,[v,g],function(e,t){function n(r){function i(){try{return document.activeElement}catch(e){return document.body}}function o(o){function a(t){return!!e.DOM.getParent(t,n.isEditorUIElement)}var s=o.editor,l,c;s.on("init",function(){"onbeforedeactivate"in document?s.dom.bind(s.getBody(),"beforedeactivate",function(){var e=s.getDoc().selection;l=e&&e.createRange?e.createRange():s.selection.getRng()}):s.inline&&(s.on("nodechange",function(){for(var e,t=document.activeElement;t;){if(t==s.getBody()){e=!0;break}t=t.parentNode}e&&(l=s.selection.getRng())}),t.webkit&&(c=function(){var e=s.selection.getRng();e.collapsed||(l=e)},e.DOM.bind(document,"selectionchange",c),s.on("remove",function(){e.DOM.unbind(document,"selectionchange",c)})))}),s.on("focusin",function(){var e=r.focusedEditor;s.selection.restoreRng&&(s.selection.setRng(s.selection.restoreRng),s.selection.restoreRng=null),e!=s&&(e&&e.fire("blur",{focusedEditor:s}),s.fire("focus",{blurredEditor:e}),s.focus(!1),r.focusedEditor=s)}),s.on("focusout",function(){s.selection.restoreRng=l,window.setTimeout(function(){var e=r.focusedEditor;e!=s&&(s.selection.restoreRng=null),a(i())||e!=s||(s.fire("blur",{focusedEditor:null}),r.focusedEditor=null,s.selection.restoreRng=null)},0)})}r.on("AddEditor",o)}return n.isEditorUIElement=function(e){return-1!==e.className.indexOf("mce-")},n}),r(st,[it,v,O,g,p,nt,ot,at],function(e,n,r,i,o,a,s,l){var c=n.DOM,u=o.explode,d=o.each,f=o.extend,p=0,h,m={majorVersion:"4",minorVersion:"0",releaseDate:"2013-07-18",editors:[],i18n:s,activeEditor:null,setup:function(){var e=this,t,n,i="",o;if(n=document.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(n)||(n+="/"),o=window.tinymce||window.tinyMCEPreInit)t=o.base||o.baseURL,i=o.suffix;else for(var a=document.getElementsByTagName("script"),s=0;s<a.length;s++){var c=a[s].src;if(/tinymce(\.jquery|)(\.min|\.dev|)\.js/.test(c)){-1!=c.indexOf(".min")&&(i=".min"),t=c.substring(0,c.lastIndexOf("/"));break}}e.baseURL=new r(n).toAbsolute(t),e.documentBaseURL=n,e.baseURI=new r(e.baseURL),e.suffix=i,e.focusManager=new l(e)},init:function(t){function n(e){var t=e.id;return t||(t=e.name,t=t&&!c.get(t)?e.name:c.uniqueId(),e.setAttribute("id",t)),t}function r(e,t,n){var r=e[t]; +if(r)return r.apply(n||this,Array.prototype.slice.call(arguments,2))}function i(e,t){return t.constructor===RegExp?t.test(e.className):c.hasClass(e,t)}var o=this,a=[],s;o.settings=t,c.bind(window,"ready",function(){var l,h;if(r(t,"onpageload"),t.types)return d(t.types,function(r){d(c.select(r.selector),function(i){var s=new e(n(i),f({},t,r),o);a.push(s),s.render(1)})}),void 0;if(t.selector)return d(c.select(t.selector),function(r){var i=new e(n(r),t,o);a.push(i),i.render(1)}),void 0;switch(t.mode){case"exact":l=t.elements||"",l.length>0&&d(u(l),function(n){c.get(n)?(s=new e(n,t,o),a.push(s),s.render(!0)):d(document.forms,function(r){d(r.elements,function(r){r.name===n&&(n="mce_editor_"+p++,c.setAttrib(r,"id",n),s=new e(n,t,o),a.push(s),s.render(1))})})});break;case"textareas":case"specific_textareas":d(c.select("textarea"),function(r){t.editor_deselector&&i(r,t.editor_deselector)||(!t.editor_selector||i(r,t.editor_selector))&&(s=new e(n(r),t,o),a.push(s),s.render(!0))})}t.oninit&&(l=h=0,d(a,function(e){h++,e.initialized?l++:e.on("init",function(){l++,l==h&&r(t,"oninit")}),l==h&&r(t,"oninit")}))})},get:function(e){return e===t?this.editors:this.editors[e]},add:function(e){var t=this,n=t.editors;return n[e.id]=e,n.push(e),t.activeEditor=e,t.fire("AddEditor",{editor:e}),h||(h=function(){t.fire("BeforeUnload")},c.bind(window,"beforeunload",h)),e},createEditor:function(t,n){return this.add(new e(t,n,this))},remove:function(e){var t=this,n,r=t.editors,i;if(e){if("string"==typeof e)return e=e.selector||e,d(c.select(e),function(e){t.remove(r[e.id])}),void 0;if(i=e,!r[i.id])return null;for(delete r[i.id],n=0;n<r.length;n++)if(r[n]==i){r.splice(n,1);break}if(t.activeEditor==i&&(t.activeEditor=r[0]),i&&!i.removed)return i.remove(),i.destroy(),t.fire("RemoveEditor",{editor:i}),r.length||c.unbind(window,"beforeunload",h),i}else for(n=r.length-1;n>=0;n--)t.remove(r[n])},execCommand:function(t,n,r){var i=this,o=i.get(r);switch(t){case"mceAddEditor":return i.get(r)||new e(r,i.settings,i).render(),!0;case"mceRemoveEditor":return o&&o.remove(),!0;case"mceToggleEditor":return o?(o.isHidden()?o.show():o.hide(),!0):(i.execCommand("mceAddEditor",0,r),!0)}return i.activeEditor?i.activeEditor.execCommand(t,n,r):!1},triggerSave:function(){d(this.editors,function(e){e.save()})},addI18n:function(e,t){s.add(e,t)},translate:function(e){return s.translate(e)}};return f(m,a),m.setup(),window.tinymce=window.tinyMCE=m,m}),r(lt,[st,p],function(e,t){var n=t.each,r=t.explode;e.on("AddEditor",function(e){var t=e.editor;t.on("preInit",function(){function e(e,t){n(t,function(t,n){t&&s.setStyle(e,n,t)}),s.rename(e,"span")}function i(e){s=t.dom,l.convert_fonts_to_spans&&n(s.select("font,u,strike",e.node),function(e){o[e.nodeName.toLowerCase()](s,e)})}var o,a,s,l=t.settings;l.inline_styles&&(a=r(l.font_size_legacy_values),o={font:function(t,n){e(n,{backgroundColor:n.style.backgroundColor,color:n.color,fontFamily:n.face,fontSize:a[parseInt(n.size,10)-1]})},u:function(t,n){e(n,{textDecoration:"underline"})},strike:function(t,n){e(n,{textDecoration:"line-through"})}},t.on("PreProcess SetContent",i))})})}),r(ct,[],function(){return{send:function(e){function t(){!e.async||4==n.readyState||r++>1e4?(e.success&&1e4>r&&200==n.status?e.success.call(e.success_scope,""+n.responseText,n,e):e.error&&e.error.call(e.error_scope,r>1e4?"TIMED_OUT":"GENERAL",n,e),n=null):setTimeout(t,10)}var n,r=0;if(e.scope=e.scope||this,e.success_scope=e.success_scope||e.scope,e.error_scope=e.error_scope||e.scope,e.async=e.async===!1?!1:!0,e.data=e.data||"",n=new XMLHttpRequest){if(n.overrideMimeType&&n.overrideMimeType(e.content_type),n.open(e.type||(e.data?"POST":"GET"),e.url,e.async),e.content_type&&n.setRequestHeader("Content-Type",e.content_type),n.setRequestHeader("X-Requested-With","XMLHttpRequest"),n.send(e.data),!e.async)return t();setTimeout(t,10)}}}}),r(ut,[],function(){function e(t,n){var r,i,o,a;if(n=n||'"',null===t)return"null";if(o=typeof t,"string"==o)return i="\bb t\nn\ff\rr\"\"''\\\\",n+t.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(e,t){return'"'===n&&"'"===e?e:(r=i.indexOf(t),r+1?"\\"+i.charAt(r+1):(e=t.charCodeAt().toString(16),"\\u"+"0000".substring(e.length)+e))})+n;if("object"==o){if(t.hasOwnProperty&&"[object Array]"===Object.prototype.toString.call(t)){for(r=0,i="[";r<t.length;r++)i+=(r>0?",":"")+e(t[r],n);return i+"]"}i="{";for(a in t)t.hasOwnProperty(a)&&(i+="function"!=typeof t[a]?(i.length>1?","+n:n)+a+n+":"+e(t[a],n):"");return i+"}"}return""+t}return{serialize:e,parse:function(e){try{return window[String.fromCharCode(101)+"val"]("("+e+")")}catch(t){}}}}),r(dt,[ut,ct,p],function(e,t,n){function r(e){this.settings=i({},e),this.count=0}var i=n.extend;return r.sendRPC=function(e){return(new r).send(e)},r.prototype={send:function(n){var r=n.error,o=n.success;n=i(this.settings,n),n.success=function(t,i){t=e.parse(t),"undefined"==typeof t&&(t={error:"JSON Parse error."}),t.error?r.call(n.error_scope||n.scope,t.error,i):o.call(n.success_scope||n.scope,t.result)},n.error=function(e,t){r&&r.call(n.error_scope||n.scope,e,t)},n.data=e.serialize({id:n.id||"c"+this.count++,method:n.method,params:n.params}),n.content_type="application/json",t.send(n)}},r}),r(ft,[v],function(e){return{callbacks:{},count:0,send:function(n){var r=this,i=e.DOM,o=n.count!==t?n.count:r.count,a="tinymce_jsonp_"+o;r.callbacks[o]=function(e){i.remove(a),delete r.callbacks[o],n.callback(e)},i.add(i.doc.body,"script",{id:a,src:n.url,type:"text/javascript"}),r.count++}}}),r(pt,[],function(){function e(){s=[];for(var e in a)s.push(e);i.length=s.length}function n(){function n(e){var n,r;return r=e!==t?c+e:i.indexOf(",",c),-1===r||r>i.length?null:(n=i.substring(c,r),c=r+1,n)}var r,i,s,c=0;a={},o.load(l),i=o.getAttribute(l)||"";do r=n(parseInt(n(),32)||0),null!==r&&(s=n(parseInt(n(),32)||0),a[r]=s);while(null!==r);e()}function r(){var t,n="";for(var r in a)t=a[r],n+=(n?",":"")+r.length.toString(32)+","+r+","+t.length.toString(32)+","+t;o.setAttribute(l,n),o.save(l),e()}var i,o,a,s,l;return window.localStorage?localStorage:(l="tinymce",o=document.documentElement,o.addBehavior("#default#userData"),i={key:function(e){return s[e]},getItem:function(e){return e in a?a[e]:null},setItem:function(e,t){a[e]=""+t,r()},removeItem:function(e){delete a[e],r()},clear:function(){a={},r()}},n(),i)}),r(ht,[v,l,y,b,p,g],function(e,t,n,r,i,o){var a=window.tinymce;return a.DOM=e.DOM,a.ScriptLoader=n.ScriptLoader,a.PluginManager=r.PluginManager,a.ThemeManager=r.ThemeManager,a.dom=a.dom||{},a.dom.Event=t.Event,i.each(i,function(e,t){a[t]=e}),i.each("isOpera isWebKit isIE isGecko isMac".split(" "),function(e){a[e]=o[e.substr(2).toLowerCase()]}),{}}),r(mt,[I,p],function(e,t){return e.extend({Defaults:{firstControlClass:"first",lastControlClass:"last"},init:function(e){this.settings=t.extend({},this.Defaults,e)},preRender:function(e){e.addClass(this.settings.containerClass,"body")},applyClasses:function(e){var t=this,n=t.settings,r,i,o;r=e.items().filter(":visible"),i=n.firstControlClass,o=n.lastControlClass,r.each(function(e){e.removeClass(i).removeClass(o),n.controlClass&&e.addClass(n.controlClass)}),r.eq(0).addClass(i),r.eq(-1).addClass(o)},renderHtml:function(e){var t=this,n=t.settings,r,i="";return r=e.items(),r.eq(0).addClass(n.firstControlClass),r.eq(-1).addClass(n.lastControlClass),r.each(function(e){n.controlClass&&e.addClass(n.controlClass),i+=e.renderHtml()}),i},recalc:function(){},postRender:function(){}})}),r(gt,[mt],function(e){return e.extend({Defaults:{containerClass:"abs-layout",controlClass:"abs-layout-item"},recalc:function(e){e.items().filter(":visible").each(function(e){var t=e.settings;e.layoutRect({x:t.x,y:t.y,w:t.w,h:t.h}),e.recalc&&e.recalc()})},renderHtml:function(e){return'<div id="'+e._id+'-absend" class="'+e.classPrefix+'abs-end"></div>'+this._super(e)}})}),r(vt,[V,G],function(e,t){return e.extend({Mixins:[t],Defaults:{classes:"widget tooltip tooltip-n"},text:function(e){var t=this;return"undefined"!=typeof e?(t._value=e,t._rendered&&(t.getEl().lastChild.innerHTML=t.encode(e)),t):t._value},renderHtml:function(){var e=this,t=e.classPrefix;return'<div id="'+e._id+'" class="'+e.classes()+'" role="presentation">'+'<div class="'+t+'tooltip-arrow"></div>'+'<div class="'+t+'tooltip-inner">'+e.encode(e._text)+"</div>"+"</div>"},repaint:function(){var e=this,t,n;t=e.getEl().style,n=e._layoutRect,t.left=n.x+"px",t.top=n.y+"px",t.zIndex=131070}})}),r(yt,[V,vt],function(e,t){var n,r=e.extend({init:function(e){var t=this;t._super(e),t.canFocus=!0,e.tooltip&&r.tooltips!==!1&&t.on("mouseenter mouseleave",function(n){var r=t.tooltip().moveTo(-65535);if(n.control==t&&"mouseenter"==n.type){var i=r.text(e.tooltip).show().testMoveRel(t.getEl(),["bc-tc","bc-tl","bc-tr"]);r.toggleClass("tooltip-n","bc-tc"==i),r.toggleClass("tooltip-nw","bc-tl"==i),r.toggleClass("tooltip-ne","bc-tr"==i),r.moveRel(t.getEl(),i)}else r.hide()}),t.aria("label",e.tooltip)},tooltip:function(){var e=this;return n||(n=new t({type:"tooltip"}),n.renderTo(e.getContainerElm())),n},active:function(e){var t=this,n;return e!==n&&(t.aria("pressed",e),t.toggleClass("active",e)),t._super(e)},disabled:function(e){var t=this,n;return e!==n&&(t.aria("disabled",e),t.toggleClass("disabled",e)),t._super(e)},postRender:function(){var e=this,t=e.settings;e._rendered=!0,e._super(),e.parent()||!t.width&&!t.height||(e.initLayoutRect(),e.repaint()),t.autofocus&&setTimeout(function(){e.focus()},0)},remove:function(){this._super(),n&&(n.remove(),n=null)}});return r}),r(bt,[yt],function(e){return e.extend({Defaults:{classes:"widget btn",role:"button"},init:function(e){var t=this,n;t.on("click mousedown",function(e){e.preventDefault()}),t._super(e),n=e.size,e.subtype&&t.addClass(e.subtype),n&&t.addClass("btn-"+n)},repaint:function(){var e=this.getEl().firstChild.style;e.width=e.height="100%",this._super()},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon,i="";return e.settings.image&&(r="none",i=" style=\"background-image: url('"+e.settings.image+"')\""),r=e.settings.icon?n+"ico "+n+"i-"+r:"",'<div id="'+t+'" class="'+e.classes()+'" tabindex="-1">'+'<button role="presentation" type="button" tabindex="-1">'+(r?'<i class="'+r+'"'+i+"></i>":"")+(e._text?(r?" ":"")+e.encode(e._text):"")+"</button>"+"</div>"}})}),r(Ct,[q],function(e){return e.extend({Defaults:{defaultType:"button",role:"toolbar"},renderHtml:function(){var e=this,t=e._layout;return e.addClass("btn-group"),e.preRender(),t.preRender(e),'<div id="'+e._id+'" class="'+e.classes()+'">'+'<div id="'+e._id+'-body">'+(e.settings.html||"")+t.renderHtml(e)+"</div>"+"</div>"}})}),r(xt,[yt],function(e){return e.extend({Defaults:{classes:"checkbox",role:"checkbox",checked:!1},init:function(e){var t=this;t._super(e),t.on("click mousedown",function(e){e.preventDefault()}),t.on("click",function(e){e.preventDefault(),t.disabled()||t.checked(!t.checked())}),t.checked(t.settings.checked)},checked:function(e){var t=this;return"undefined"!=typeof e?(e?t.addClass("checked"):t.removeClass("checked"),t._checked=e,t.aria("checked",e),t):t._checked},value:function(e){return this.checked(e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'<div id="'+t+'" class="'+e.classes()+'" unselectable="on" aria-labeledby="'+t+'-al" tabindex="-1">'+'<i class="'+n+"ico "+n+'i-checkbox"></i>'+'<span id="'+t+'-al" class="'+n+'label">'+e.encode(e._text)+"</span>"+"</div>"}})}),r(wt,[bt,X],function(e,t){return e.extend({showPanel:function(){var e=this,n=e.settings;n.panel.popover=!0,n.panel.autohide=!0,e.active(!0),e.panel?e.panel.show():(e.panel=new t(n.panel).on("hide",function(){e.active(!1)}).parent(e).renderTo(e.getContainerElm()),e.panel.fire("show"),e.panel.reflow()),e.panel.moveRel(e.getEl(),n.popoverAlign||"bc-tc")},hidePanel:function(){var e=this;e.panel&&e.panel.hide()},postRender:function(){var e=this;return e.on("click",function(t){t.control===e&&(e.panel&&e.panel.visible()?e.hidePanel():e.showPanel())}),e._super()}})}),r(_t,[wt,v],function(e,t){var n=t.DOM;return e.extend({init:function(e){this._super(e),this.addClass("colorbutton")},color:function(e){return e?(this._color=e,this.getEl("preview").style.backgroundColor=e,this):this._color},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon?n+"ico "+n+"i-"+e.settings.icon:"",i=e.settings.image?" style=\"background-image: url('"+e.settings.image+"')\"":"";return'<div id="'+t+'" class="'+e.classes()+'">'+'<button role="presentation" hidefocus type="button" tabindex="-1">'+(r?'<i class="'+r+'"'+i+"></i>":"")+'<span id="'+t+'-preview" class="'+n+'preview"></span>'+(e._text?(r?" ":"")+e._text:"")+"</button>"+'<button type="button" class="'+n+'open" hidefocus tabindex="-1">'+' <i class="'+n+'caret"></i>'+"</button>"+"</div>"},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(r){r.control!=e||n.getParent(r.target,"."+e.classPrefix+"open")||(r.stopImmediatePropagation(),t.call(e,r))}),delete e.settings.onclick,e._super()}})}),r(Nt,[yt,z],function(e,t){return e.extend({init:function(e){var n=this;n._super(e),n.addClass("combobox"),n.on("click",function(e){for(var t=e.target;t;)t.id&&-1!=t.id.indexOf("-open")&&n.fire("action"),t=t.parentNode}),n.on("keydown",function(e){"INPUT"==e.target.nodeName&&13==e.keyCode&&n.parents().reverse().each(function(t){return e.preventDefault(),n.fire("change"),t.submit?(t.submit(),!1):void 0})}),e.placeholder&&(n.addClass("placeholder"),n.on("focusin",function(){n._hasOnChange||(t.on(n.getEl("inp"),"change",function(){n.fire("change")}),n._hasOnChange=!0),n.hasClass("placeholder")&&(n.getEl("inp").value="",n.removeClass("placeholder"))}),n.on("focusout",function(){0===n.value().length&&(n.getEl("inp").value=e.placeholder,n.addClass("placeholder"))}))},value:function(e){var t=this;return"undefined"!=typeof e?(t._value=e,t.removeClass("placeholder"),t._rendered&&(t.getEl("inp").value=e),t):t._rendered?(e=t.getEl("inp").value,e!=t.settings.placeholder?e:""):t._value},disabled:function(e){var t=this;t._super(e),t._rendered&&(t.getEl("inp").disabled=e)},focus:function(){this.getEl("inp").focus()},repaint:function(){var e=this,n=e.getEl(),r=e.getEl("open"),i=e.layoutRect(),o,a;o=r?i.w-r.offsetWidth-10:i.w-10;var s=document;return s.all&&(!s.documentMode||s.documentMode<=8)&&(a=e.layoutRect().h-2+"px"),t.css(n.firstChild,{width:o,lineHeight:a}),e._super(),e},postRender:function(){var e=this;return t.on(this.getEl("inp"),"change",function(){e.fire("change")}),e._super()},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.classPrefix,i=n.value||n.placeholder||"",o,a,s="";return o=n.icon?r+"ico "+r+"i-"+n.icon:"",a=e._text,(o||a)&&(s='<div id="'+t+'-open" class="'+r+"btn "+r+'open" tabIndex="-1">'+'<button id="'+t+'-action" type="button" hidefocus tabindex="-1">'+(o?'<i class="'+o+'"></i>':'<i class="'+r+'caret"></i>')+(a?(o?" ":"")+a:"")+"</button>"+"</div>",e.addClass("has-open")),'<div id="'+t+'" class="'+e.classes()+'">'+'<input id="'+t+'-inp" class="'+r+"textbox "+r+'placeholder" value="'+i+'" hidefocus="true">'+s+"</div>"}})}),r(Et,[V,J],function(e,t){return e.extend({Defaults:{delimiter:"\xbb"},init:function(e){var t=this;t._super(e),t.addClass("path"),t.canFocus=!0,t.on("click",function(e){var n,r=e.target;(n=r.getAttribute("data-index"))&&t.fire("select",{value:t.data()[n],index:n})})},focus:function(){var e=this;return e.keyNav=new t({root:e,enableLeftRight:!0}),e.keyNav.focusFirst(),e},data:function(e){var t=this;return"undefined"!=typeof e?(t._data=e,t.update(),t):t._data},update:function(){this.getEl().innerHTML=this._getPathHtml()},postRender:function(){var e=this;e._super(),e.data(e.settings.data)},renderHtml:function(){var e=this;return'<div id="'+e._id+'" class="'+e.classPrefix+'path">'+e._getPathHtml()+"</div>"},_getPathHtml:function(){var e=this,t=e._data||[],n,r,i="",o=e.classPrefix;for(n=0,r=t.length;r>n;n++)i+=(n>0?'<div class="'+o+'divider" aria-hidden="true"> '+e.settings.delimiter+" </div>":"")+'<div role="button" class="'+o+"path-item"+(n==r-1?" "+o+"last":"")+'" data-index="'+n+'" tabindex="-1" id="'+e._id+"-"+n+'">'+t[n].name+"</div>";return i||(i='<div class="'+o+'path-item"> </div>'),i}})}),r(St,[Et,st],function(e,t){return e.extend({postRender:function(){function e(e){return 1===e.nodeType&&("BR"==e.nodeName||!!e.getAttribute("data-mce-bogus"))}var n=this,r=t.activeEditor;return n.on("select",function(t){var n=[],i,o=r.getBody();for(r.focus(),i=r.selection.getStart();i&&i!=o;)e(i)||n.push(i),i=i.parentNode;r.selection.select(n[n.length-1-t.index]),r.nodeChanged()}),r.on("nodeChange",function(t){for(var i=[],o=t.parents,a=o.length;a--;)if(1==o[a].nodeType&&!e(o[a])){var s=r.fire("ResolveName",{name:o[a].nodeName.toLowerCase(),target:o[a]});i.push({name:s.name})}n.data(i)}),n._super()}})}),r(kt,[q],function(e){return e.extend({Defaults:{layout:"flex",align:"center",defaults:{flex:1}},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.addClass("formitem"),t.preRender(e),'<div id="'+e._id+'" class="'+e.classes()+'" hideFocus="1" tabIndex="-1">'+(e.settings.title?'<div id="'+e._id+'-title" class="'+n+'title">'+e.settings.title+"</div>":"")+'<div id="'+e._id+'-body" class="'+e.classes("body")+'">'+(e.settings.html||"")+t.renderHtml(e)+"</div>"+"</div>"}})}),r(Tt,[q,kt],function(e,t){return e.extend({Defaults:{containerCls:"form",layout:"flex",direction:"column",align:"stretch",flex:1,padding:20,labelGap:30,spacing:10},preRender:function(){var e=this,n=e.items();n.each(function(n){var r,i=n.settings.label;i&&(r=new t({layout:"flex",autoResize:"overflow",defaults:{flex:1},items:[{type:"label",text:i,flex:0,forId:n._id}]}),r.type="formitem","undefined"==typeof n.settings.flex&&(n.settings.flex=1),e.replace(n,r),r.add(n))})},recalcLabels:function(){var e=this,t=0,n=[],r,i;if(e.settings.labelGapCalc!==!1)for(e.items().filter("formitem").each(function(e){var r=e.items()[0],i=r.getEl().clientWidth;t=i>t?i:t,n.push(r)}),i=e.settings.labelGap||0,r=n.length;r--;)n[r].settings.minWidth=t+i},visible:function(e){var t=this._super(e);return e===!0&&this._rendered&&this.recalcLabels(),t},submit:function(){var e=this.getParentCtrl(document.activeElement);return e&&e.blur(),this.fire("submit",{data:this.toJSON()})},postRender:function(){var e=this;e._super(),e.recalcLabels(),e.fromJSON(e.settings.data)}})}),r(Rt,[Tt],function(e){return e.extend({Defaults:{containerCls:"fieldset",layout:"flex",direction:"column",align:"stretch",flex:1,padding:"25 15 5 15",labelGap:30,spacing:10,border:1},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.preRender(),t.preRender(e),'<fieldset id="'+e._id+'" class="'+e.classes()+'" hideFocus="1" tabIndex="-1">'+(e.settings.title?'<legend id="'+e._id+'-title" class="'+n+'fieldset-title">'+e.settings.title+"</legend>":"")+'<div id="'+e._id+'-body" class="'+e.classes("body")+'">'+(e.settings.html||"")+t.renderHtml(e)+"</div>"+"</fieldset>"}})}),r(At,[Nt],function(e){return e.extend({init:function(e){var t=this,n=tinymce.activeEditor,r;e.spellcheck=!1,r=n.settings.file_browser_callback,r&&(e.icon="browse",e.onaction=function(){r(t.getEl("inp").id,t.getEl("inp").value,e.filetype,window)}),t._super(e)}})}),r(Bt,[gt],function(e){return e.extend({recalc:function(e){var t=e.layoutRect(),n=e.paddingBox();e.items().filter(":visible").each(function(e){e.layoutRect({x:n.left,y:n.top,w:t.innerW-n.right-n.left,h:t.innerH-n.top-n.bottom}),e.recalc&&e.recalc()})}})}),r(Lt,[gt],function(e){return e.extend({recalc:function(e){var t,n,r,i,o,a,s,l,c,u,d,f,p,h,m,g,v=[],y,b,C,x,w,_,N,E,S,k,T,R,A,B,L,M,D,H,P,O,I,F,W,z,V=Math.max,U=Math.min;for(r=e.items().filter(":visible"),i=e.layoutRect(),o=e._paddingBox,a=e.settings,f=a.direction,s=a.align,l=a.pack,c=a.spacing||0,("row-reversed"==f||"column-reverse"==f)&&(r=r.set(r.toArray().reverse()),f=f.split("-")[0]),"column"==f?(S="y",N="h",E="minH",k="maxH",R="innerH",T="top",A="bottom",B="deltaH",L="contentH",I="left",H="w",M="x",D="innerW",P="minW",O="maxW",F="right",W="deltaW",z="contentW"):(S="x",N="w",E="minW",k="maxW",R="innerW",T="left",A="right",B="deltaW",L="contentW",I="top",H="h",M="y",D="innerH",P="minH",O="maxH",F="bottom",W="deltaH",z="contentH"),d=i[R]-o[T]-o[T],_=u=0,t=0,n=r.length;n>t;t++)p=r[t],h=p.layoutRect(),m=p.settings,g=m.flex,d-=n-1>t?c:0,g>0&&(u+=g,h[k]&&v.push(p),h.flex=g),d-=h[E],y=o[I]+h[P]+o[F],y>_&&(_=y);if(x={},x[E]=0>d?i[E]-d+i[B]:i[R]-d+i[B],x[P]=_+i[W],x[L]=i[R]-d,x[z]=_,x.minW=U(x.minW,i.maxW),x.minH=U(x.minH,i.maxH),x.minW=V(x.minW,i.startMinWidth),x.minH=V(x.minH,i.startMinHeight),!i.autoResize||x.minW==i.minW&&x.minH==i.minH){for(C=d/u,t=0,n=v.length;n>t;t++)p=v[t],h=p.layoutRect(),b=h[k],y=h[E]+Math.ceil(h.flex*C),y>b?(d-=h[k]-h[E],u-=h.flex,h.flex=0,h.maxFlexSize=b):h.maxFlexSize=0;for(C=d/u,w=o[T],x={},0===u&&("end"==l?w=d+o[T]:"center"==l?(w=Math.round(i[R]/2-(i[R]-d)/2)+o[T],0>w&&(w=o[T])):"justify"==l&&(w=o[T],c=Math.floor(d/(r.length-1)))),x[M]=o[I],t=0,n=r.length;n>t;t++)p=r[t],h=p.layoutRect(),y=h.maxFlexSize||h[E],"center"===s?x[M]=Math.round(i[D]/2-h[H]/2):"stretch"===s?(x[H]=V(h[P]||0,i[D]-o[I]-o[F]),x[M]=o[I]):"end"===s&&(x[M]=i[D]-h[H]-o.top),h.flex>0&&(y+=Math.ceil(h.flex*C)),x[N]=y,x[S]=w,p.layoutRect(x),p.recalc&&p.recalc(),w+=y+c}else if(x.w=x.minW,x.h=x.minH,e.layoutRect(x),this.recalc(e),null===e._lastRect){var q=e.parent();q&&(q._lastRect=null,q.recalc())}}})}),r(Mt,[mt],function(e){return e.extend({Defaults:{containerClass:"flow-layout",controlClass:"flow-layout-item",endClass:"break"},recalc:function(e){e.items().filter(":visible").each(function(e){e.recalc&&e.recalc()})}})}),r(Dt,[U,V,yt,X,p,st,g],function(e,t,n,r,i,o,a){function s(e){function t(e){return e.replace(/%(\w+)/g,"")}var n=o.activeEditor,r,i,a=n.dom,s="",l,c;return c=n.settings.preview_styles,c===!1?"":(c||(c="font-family font-size font-weight text-decoration text-transform color background-color border border-radius"),(e=n.formatter.get(e))?(e=e[0],r=e.block||e.inline||"span",i=a.create(r),u(e.styles,function(e,n){e=t(e),e&&a.setStyle(i,n,e)}),u(e.attributes,function(e,n){e=t(e),e&&a.setAttrib(i,n,e)}),u(e.classes,function(e){e=t(e),a.hasClass(i,e)||a.addClass(i,e)}),n.fire("PreviewFormats"),a.setStyles(i,{position:"absolute",left:-65535}),n.getBody().appendChild(i),l=a.getStyle(n.getBody(),"fontSize",!0),l=/px$/.test(l)?parseInt(l,10):0,u(c.split(" "),function(e){var t=a.getStyle(i,e,!0);if(!("background-color"==e&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(t)&&(t=a.getStyle(n.getBody(),e,!0),"#ffffff"==a.toHex(t).toLowerCase())||"color"==e&&"#000000"==a.toHex(t).toLowerCase())){if("font-size"==e&&/em|%$/.test(t)){if(0===l)return;t=parseFloat(t,10)/(/%$/.test(t)?100:1),t=t*l+"px"}"border"==e&&t&&(s+="padding:0 2px;"),s+=e+":"+t+";"}}),n.fire("AfterPreviewFormats"),a.remove(i),s):void 0)}function l(e,t){return function(){var n=this;o.activeEditor.on("nodeChange",function(r){var i=o.activeEditor.formatter,a=null;u(r.parents,function(n){return u(e,function(e){return t?i.matchNode(n,t,{value:e.value})&&(a=e.value):i.matchNode(n,e.value)&&(a=e.value),a?!1:void 0}),a?!1:void 0}),n.value(a)})}}function c(e){e=e.split(";");for(var t=e.length;t--;)e[t]=e[t].split("=");return e}var u=i.each;t.translate=function(e){return o.translate(e)},n.tooltips=!a.iOS,o.on("AddEditor",function(t){function n(){function e(r){var i=[];if(r)return u(r,function(r){var o={text:r.title,icon:r.icon,preview:!0};if(r.items)o.menu=e(r.items);else{var a=r.format||"custom"+t++;r.format||(r.name=a,n.push(r)),o.textStyle=function(){return s(a)},o.onclick=function(){m(a)},o.onPostRender=function(){var e=this;e.parent().on("show",function(){e.disabled(!g.formatter.canApply(a)),e.active(g.formatter.match(a))})}}i.push(o)}),i}var t=0,n=[],r=[{title:"Headers",items:[{title:"Header 1",format:"h1"},{title:"Header 2",format:"h2"},{title:"Header 3",format:"h3"},{title:"Header 4",format:"h4"},{title:"Header 5",format:"h5"},{title:"Header 6",format:"h6"}]},{title:"Inline",items:[{title:"Bold",icon:"bold",format:"bold"},{title:"Italic",icon:"italic",format:"italic"},{title:"Underline",icon:"underline",format:"underline"},{title:"Strikethrough",icon:"strikethrough",format:"strikethrough"},{title:"Superscript",icon:"superscript",format:"superscript"},{title:"Subscript",icon:"subscript",format:"subscript"},{title:"Code",icon:"code",format:"code"}]},{title:"Blocks",items:[{title:"Paragraph",format:"p"},{title:"Blockquote",format:"blockquote"},{title:"Div",format:"div"},{title:"Pre",format:"pre"}]},{title:"Alignment",items:[{title:"Left",icon:"alignleft",format:"alignleft"},{title:"Center",icon:"aligncenter",format:"aligncenter"},{title:"Right",icon:"alignright",format:"alignright"},{title:"Justify",icon:"alignjustify",format:"alignjustify"}]}];g.on("init",function(){u(n,function(e){g.formatter.register(e.name,e)})});var i=e(g.settings.style_formats||r);return i}function a(){return g.undoManager?g.undoManager.hasUndo():!1}function d(){return g.undoManager?g.undoManager.hasRedo():!1}function f(){var e=this;e.disabled(!a()),g.on("Undo Redo AddUndo TypingUndo",function(){e.disabled(!a())})}function p(){var e=this;e.disabled(!d()),g.on("Undo Redo AddUndo TypingUndo",function(){e.disabled(!d())})}function h(){var e=this;g.on("VisualAid",function(t){e.active(t.hasVisual)}),e.active(g.hasVisual)}function m(e){e.control&&(e=e.control.value()),e&&o.activeEditor.execCommand("mceToggleFormat",!1,e)}var g=t.editor,v;v=n(),u({bold:"Bold",italic:"Italic",underline:"Underline",strikethrough:"Strikethrough",subscript:"Subscript",superscript:"Superscript"},function(e,t){g.addButton(t,{tooltip:e,onPostRender:function(){var e=this;g.formatter?g.formatter.formatChanged(t,function(t){e.active(t)}):g.on("init",function(){g.formatter.formatChanged(t,function(t){e.active(t)})})},onclick:function(){m(t)}})}),u({outdent:["Decrease indent","Outdent"],indent:["Increase indent","Indent"],cut:["Cut","Cut"],copy:["Copy","Copy"],paste:["Paste","Paste"],help:["Help","mceHelp"],selectall:["Select all","SelectAll"],hr:["Insert horizontal rule","InsertHorizontalRule"],removeformat:["Clear formatting","RemoveFormat"],visualaid:["Visual aids","mceToggleVisualAid"],newdocument:["New document","mceNewDocument"]},function(e,t){g.addButton(t,{tooltip:e[0],cmd:e[1]})}),u({blockquote:["Toggle blockquote","mceBlockQuote"],numlist:["Numbered list","InsertOrderedList"],bullist:["Bulleted list","InsertUnorderedList"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],alignleft:["Align left","JustifyLeft"],aligncenter:["Align center","JustifyCenter"],alignright:["Align right","JustifyRight"],alignjustify:["Justify","JustifyFull"]},function(e,t){g.addButton(t,{tooltip:e[0],cmd:e[1],onPostRender:function(){var e=this;g.formatter?g.formatter.formatChanged(t,function(t){e.active(t)}):g.on("init",function(){g.formatter.formatChanged(t,function(t){e.active(t)})})}})}),g.addButton("undo",{tooltip:"Undo",onPostRender:f,cmd:"undo"}),g.addButton("redo",{tooltip:"Redo",onPostRender:p,cmd:"redo"}),g.addMenuItem("newdocument",{text:"New document",shortcut:"Ctrl+N",icon:"newdocument",cmd:"mceNewDocument"}),g.addMenuItem("undo",{text:"Undo",icon:"undo",shortcut:"Ctrl+Z",onPostRender:f,cmd:"undo"}),g.addMenuItem("redo",{text:"Redo",icon:"redo",shortcut:"Ctrl+Y",onPostRender:p,cmd:"redo"}),g.addMenuItem("visualaid",{text:"Visual aids",selectable:!0,onPostRender:h,cmd:"mceToggleVisualAid"}),u({cut:["Cut","Cut","Ctrl+X"],copy:["Copy","Copy","Ctrl+C"],paste:["Paste","Paste","Ctrl+V"],selectall:["Select all","SelectAll","Ctrl+A"],bold:["Bold","Bold","Ctrl+B"],italic:["Italic","Italic","Ctrl+I"],underline:["Underline","Underline"],strikethrough:["Strikethrough","Strikethrough"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],removeformat:["Clear formatting","RemoveFormat"]},function(e,t){g.addMenuItem(t,{text:e[0],icon:t,shortcut:e[2],cmd:e[1]})}),g.on("mousedown",function(){r.hideAll()}),e.add("styleselect",function(t){var n=[].concat(v);return e.create("menubutton",i.extend({text:"Formats",menu:n},t))}),e.add("formatselect",function(t){var n=[],r=c(g.settings.block_formats||"Paragraph=p;Address=address;Pre=pre;Header 1=h1;Header 2=h2;Header 3=h3;Header 4=h4;Header 5=h5;Header 6=h6");return u(r,function(e){n.push({text:{raw:e[0]},value:e[1],textStyle:function(){return s(e[1])}})}),e.create("listbox",i.extend({text:{raw:r[0][0]},values:n,fixedWidth:!0,onselect:m,onPostRender:l(n)},t))}),e.add("fontselect",function(t){var n="Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",r=[],a=c(g.settings.font_formats||n);return u(a,function(e){r.push({text:{raw:e[0]},value:e[1],textStyle:-1==e[1].indexOf("dings")?"font-family:"+e[1]:""})}),e.create("listbox",i.extend({text:"Font Family",tooltip:"Font Family",values:r,fixedWidth:!0,onPostRender:l(r,"fontname"),onselect:function(e){e.control.settings.value&&o.activeEditor.execCommand("FontName",!1,e.control.settings.value)}},t))}),e.add("fontsizeselect",function(t){var n=[],r="8pt 10pt 12pt 14pt 18pt 24pt 36pt",a=g.settings.fontsize_formats||r;return u(a.split(" "),function(e){n.push({text:e,value:e})}),e.create("listbox",i.extend({text:"Font Sizes",tooltip:"Font Sizes",values:n,fixedWidth:!0,onPostRender:l(n,"fontsize"),onclick:function(e){e.control.settings.value&&o.activeEditor.execCommand("FontSize",!1,e.control.settings.value)}},t))}),g.addMenuItem("formats",{text:"Formats",menu:v})})}),r(Ht,[gt],function(e){return e.extend({recalc:function(e){var t=e.settings,n,r,i,o,a,s,l,c,u,d,f,p,h,m,g,v,y,b,C,x,w,_,N=[],E=[],S,k,T,R,A,B;for(t=e.settings,i=e.items().filter(":visible"),o=e.layoutRect(),r=t.columns||Math.ceil(Math.sqrt(i.length)),n=Math.ceil(i.length/r),y=t.spacingH||t.spacing||0,b=t.spacingV||t.spacing||0,C=t.alignH||t.align,x=t.alignV||t.align,g=e._paddingBox,C&&"string"==typeof C&&(C=[C]),x&&"string"==typeof x&&(x=[x]),d=0;r>d;d++)N.push(0);for(f=0;n>f;f++)E.push(0);for(f=0;n>f;f++)for(d=0;r>d&&(u=i[f*r+d],u);d++)c=u.layoutRect(),S=c.minW,k=c.minH,N[d]=S>N[d]?S:N[d],E[f]=k>E[f]?k:E[f];for(A=o.innerW-g.left-g.right,w=0,d=0;r>d;d++)w+=N[d]+(d>0?y:0),A-=(d>0?y:0)+N[d];for(B=o.innerH-g.top-g.bottom,_=0,f=0;n>f;f++)_+=E[f]+(f>0?b:0),B-=(f>0?b:0)+E[f];if(w+=g.left+g.right,_+=g.top+g.bottom,l={},l.minW=w+(o.w-o.innerW),l.minH=_+(o.h-o.innerH),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH,l.minW=Math.min(l.minW,o.maxW),l.minH=Math.min(l.minH,o.maxH),l.minW=Math.max(l.minW,o.startMinWidth),l.minH=Math.max(l.minH,o.startMinHeight),!o.autoResize||l.minW==o.minW&&l.minH==o.minH){o.autoResize&&(l=e.layoutRect(l),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH);var L;L="start"==t.packV?0:B>0?Math.floor(B/n):0;var M=0,D=t.flexWidths;if(D)for(d=0;d<D.length;d++)M+=D[d];else M=r;var H=A/M;for(d=0;r>d;d++)N[d]+=D?Math.ceil(D[d]*H):H;for(h=g.top,f=0;n>f;f++){for(p=g.left,s=E[f]+L,d=0;r>d&&(u=i[f*r+d],u);d++)m=u.settings,c=u.layoutRect(),a=N[d],T=R=0,c.x=p,c.y=h,v=m.alignH||(C?C[d]||C[0]:null),"center"==v?c.x=p+a/2-c.w/2:"right"==v?c.x=p+a-c.w:"stretch"==v&&(c.w=a),v=m.alignV||(x?x[d]||x[0]:null),"center"==v?c.y=h+s/2-c.h/2:"bottom"==v?c.y=h+s-c.h:"stretch"==v&&(c.h=s),u.layoutRect(c),p+=a+y,u.recalc&&u.recalc();h+=s+b}}else if(l.w=l.minW,l.h=l.minH,e.layoutRect(l),this.recalc(e),null===e._lastRect){var P=e.parent();P&&(P._lastRect=null,P.recalc())}}})}),r(Pt,[yt],function(e){return e.extend({renderHtml:function(){var e=this;return e.addClass("iframe"),e.canFocus=!1,'<iframe id="'+e._id+'" class="'+e.classes()+'" tabindex="-1" src="'+(e.settings.url||"javascript:''")+'" frameborder="0"></iframe>'},src:function(e){this.getEl().src=e +},html:function(e){return this.getEl().contentWindow.document.body.innerHTML=e,this}})}),r(Ot,[yt],function(e){return e.extend({init:function(e){var t=this;t._super(e),t.addClass("widget"),t.addClass("label"),t.canFocus=!1,e.multiline&&t.addClass("autoscroll"),e.strong&&t.addClass("strong")},initLayoutRect:function(){var e=this,t=e._super();return e.settings.multiline&&(e.getEl().offsetWidth>t.maxW&&(t.minW=t.maxW,e.addClass("multiline")),e.getEl().style.width=t.minW+"px",t.startMinH=t.h=t.minH=Math.min(t.maxH,e.getEl().offsetHeight)),t},disabled:function(e){var t=this,n;return e!==n&&(t.toggleClass("label-disabled",e),t._rendered&&(t.getEl()[0].className=t.classes())),t._super(e)},repaint:function(){var e=this;return e.settings.multiline||(e.getEl().style.lineHeight=e.layoutRect().h+"px"),e._super()},text:function(e){var t=this;return t._rendered&&e&&(t.getEl().innerHTML=t.encode(e)),t._super(e)},renderHtml:function(){var e=this,t=e.settings.forId;return'<label id="'+e._id+'" class="'+e.classes()+'"'+(t?' for="'+t:"")+'">'+e.encode(e._text)+"</label>"}})}),r(It,[q,J],function(e,t){return e.extend({Defaults:{role:"toolbar",layout:"flow"},init:function(e){var t=this;t._super(e),t.addClass("toolbar")},postRender:function(){var e=this;return e.items().addClass("toolbar-item"),e.keyNav=new t({root:e,enableLeftRight:!0}),e._super()}})}),r(Ft,[It],function(e){return e.extend({Defaults:{role:"menubar",containerCls:"menubar",defaults:{type:"menubutton"}}})}),r(Wt,[bt,U,Ft],function(e,t,n){function r(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1}var i=e.extend({init:function(e){var t=this;t._renderOpen=!0,t._super(e),t.addClass("menubtn"),e.fixedWidth&&t.addClass("fixed-width"),t.aria("haspopup",!0),t.hasPopup=!0},showMenu:function(){var e=this,n=e.settings,r;return e.menu&&e.menu.visible()?e.hideMenu():(e.menu||(r=n.menu||[],r.length?r={type:"menu",items:r}:r.type=r.type||"menu",e.menu=t.create(r).parent(e).renderTo(e.getContainerElm()),e.fire("createmenu"),e.menu.reflow(),e.menu.on("cancel",function(t){t.control===e.menu&&e.focus()}),e.menu.on("show hide",function(t){t.control==e.menu&&e.activeMenu("show"==t.type)}).fire("show"),e.aria("expanded",!0)),e.menu.show(),e.menu.layoutRect({w:e.layoutRect().w}),e.menu.moveRel(e.getEl(),["bl-tl","tl-bl"]),void 0)},hideMenu:function(){var e=this;e.menu&&(e.menu.items().each(function(e){e.hideMenu&&e.hideMenu()}),e.menu.hide(),e.aria("expanded",!1))},activeMenu:function(e){this.toggleClass("active",e)},renderHtml:function(){var e=this,t=e._id,r=e.classPrefix,i=e.settings.icon?r+"ico "+r+"i-"+e.settings.icon:"";return e.aria("role",e.parent()instanceof n?"menuitem":"button"),'<div id="'+t+'" class="'+e.classes()+'" tabindex="-1">'+'<button id="'+t+'-open" role="presentation" type="button" tabindex="-1">'+(i?'<i class="'+i+'"></i>':"")+"<span>"+(e._text?(i?" ":"")+e.encode(e._text):"")+"</span>"+' <i class="'+r+'caret"></i>'+"</button>"+"</div>"},postRender:function(){var e=this;return e.on("click",function(t){t.control===e&&r(t.target,e.getEl())&&(e.showMenu(),t.keyboard&&e.menu.items()[0].focus())}),e.on("mouseenter",function(t){var n=t.control,r=e.parent(),o;n&&r&&n instanceof i&&n.parent()==r&&(r.items().filter("MenuButton").each(function(e){e.hideMenu&&e!=n&&(e.menu&&e.menu.visible()&&(o=!0),e.hideMenu())}),o&&(n.focus(),n.showMenu()))}),e._super()},text:function(e){var t=this,n,r;if(t._rendered)for(r=t.getEl("open").getElementsByTagName("span"),n=0;n<r.length;n++)r[n].innerHTML=t.encode(e);return this._super(e)},remove:function(){this._super(),this.menu&&this.menu.remove()}});return i}),r(zt,[Wt],function(e){return e.extend({init:function(e){var t=this,n,r,i,o,a;if(t._values=n=e.values,n){for(r=0;r<n.length;r++)i=n[r].selected||e.value===n[r].value,i&&(o=o||n[r].text,t._value=n[r].value);e.menu=n}e.text=e.text||o||n[0].text,t._super(e),t.addClass("listbox"),t.on("select",function(n){var r=n.control;a&&(n.lastControl=a),e.multiple?r.active(!r.active()):t.value(n.control.settings.value),a=r})},value:function(e){function t(e,n){e.items().each(function(e){r=e.value()===n,r&&(i=i||e.text()),e.active(r),e.menu&&t(e.menu,n)})}var n=this,r,i,o,a;if("undefined"!=typeof e){if(n.menu)t(n.menu,e);else for(o=n.settings.menu,a=0;a<o.length;a++)r=o[a].value==e,r&&(i=i||o[a].text),o[a].active=r;n.text(i||this.settings.text)}return n._super(e)}})}),r(Vt,[yt,U],function(e,t){return e.extend({Defaults:{border:0,role:"menuitem"},init:function(e){var t=this;t.hasPopup=!0,t._super(e),e=t.settings,t.addClass("menu-item"),e.menu&&t.addClass("menu-item-expand"),e.preview&&t.addClass("menu-item-preview"),("-"===t._text||"|"===t._text)&&(t.addClass("menu-item-sep"),t.aria("role","separator"),t.canFocus=!1,t._text="-"),e.selectable&&(t.aria("role","menuitemcheckbox"),t.aria("checked",!0),t.addClass("menu-item-checkbox"),e.icon="selected"),t.on("mousedown",function(e){e.preventDefault()}),t.on("mouseenter click",function(n){n.control===t&&(e.menu||"click"!==n.type?(t.showMenu(),n.keyboard&&setTimeout(function(){t.menu.items()[0].focus()},0)):(t.parent().hideAll(),t.fire("cancel"),t.fire("select")))}),e.menu&&t.aria("haspopup",!0)},hasMenus:function(){return!!this.settings.menu},showMenu:function(){var e=this,n=e.settings,r;if(e.parent().items().each(function(t){t!==e&&t.hideMenu()}),n.menu){r=e.menu,r?r.show():(r=n.menu,r.length?r={type:"menu",items:r}:r.type=r.type||"menu",r=e.menu=t.create(r).parent(e).renderTo(e.getContainerElm()),r.reflow(),r.fire("show"),r.on("cancel",function(){e.focus()}),r.on("hide",function(t){t.control===r&&e.removeClass("selected")})),r._parentMenu=e.parent(),r.addClass("menu-sub");var i=r.testMoveRel(e.getEl(),["tr-tl","br-bl","tl-tr","bl-br"]);r.moveRel(e.getEl(),i),i="menu-sub-"+i,r.removeClass(r._lastRel),r.addClass(i),r._lastRel=i,e.addClass("selected"),e.aria("expanded",!0)}},hideMenu:function(){var e=this;return e.menu&&(e.menu.items().each(function(e){e.hideMenu&&e.hideMenu()}),e.menu.hide(),e.aria("expanded",!1)),e},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.classPrefix,i=e.encode(e._text),o=e.settings.icon;return o&&e.parent().addClass("menu-has-icons"),o=r+"ico "+r+"i-"+(e.settings.icon||"none"),'<div id="'+t+'" class="'+e.classes()+'" tabindex="-1">'+("-"!==i?'<i class="'+o+'"></i> ':"")+("-"!==i?'<span id="'+t+'-text" class="'+r+'text">'+i+"</span>":"")+(n.shortcut?'<div id="'+t+'-shortcut" class="'+r+'menu-shortcut">'+n.shortcut+"</div>":"")+(n.menu?'<div class="'+r+'caret"></div>':"")+"</div>"},postRender:function(){var e=this,t=e.settings,n=t.textStyle;if("function"==typeof n&&(n=n()),n){var r=e.getEl("text");r&&r.setAttribute("style",n)}return e._super()},remove:function(){this._super(),this.menu&&this.menu.remove()}})}),r(Ut,[X,J,Vt],function(e,t,n){var r=e.extend({Defaults:{defaultType:"menuitem",border:1,layout:"stack",role:"menu"},init:function(e){var r=this;e.autohide=!0,e.constrainToViewport=!0,r._super(e),r.addClass("menu"),r.keyNav=new t({root:r,enableUpDown:!0,enableLeftRight:!0,leftAction:function(){r.parent()instanceof n&&r.keyNav.cancel()},onCancel:function(){r.fire("cancel",{},!1),r.hide()}})},repaint:function(){return this.toggleClass("menu-align",!0),this._super(),this.getEl().style.height="",this.getEl("body").style.height="",this},cancel:function(){var e=this;e.hideAll(),e.fire("cancel"),e.fire("select")},hideAll:function(){var e=this;return this.find("menuitem").exec("hideMenu"),e._super()},preRender:function(){var e=this;return e.items().each(function(t){var n=t.settings;return n.icon||n.selectable?(e._hasIcons=!0,!1):void 0}),e._super()}});return r}),r(qt,[xt],function(e){return e.extend({Defaults:{classes:"radio",role:"radio"}})}),r($t,[yt,$],function(e,t){return e.extend({renderHtml:function(){var e=this,t=e.classPrefix;return e.addClass("resizehandle"),"both"==e.settings.direction&&e.addClass("resizehandle-both"),e.canFocus=!1,'<div id="'+e._id+'" class="'+e.classes()+'">'+'<i class="'+t+"ico "+t+'i-resize"></i>'+"</div>"},postRender:function(){var e=this;e._super(),e.resizeDragHelper=new t(this._id,{start:function(){e.fire("ResizeStart")},drag:function(t){"both"!=e.settings.direction&&(t.deltaX=0),e.fire("Resize",t)},end:function(){e.fire("ResizeEnd")}})}})}),r(jt,[yt],function(e){return e.extend({renderHtml:function(){var e=this;return e.addClass("spacer"),e.canFocus=!1,'<div id="'+e._id+'" class="'+e.classes()+'"></div>'}})}),r(Kt,[Wt,v],function(e,t){var n=t.DOM;return e.extend({Defaults:{classes:"widget btn splitbtn",role:"splitbutton"},repaint:function(){var e=this,t=e.getEl(),r=e.layoutRect(),i,o,a;return e._super(),i=t.firstChild,o=t.lastChild,n.css(i,{width:r.w-o.offsetWidth,height:r.h-2}),n.css(o,{height:r.h-2}),a=i.firstChild.style,a.width=a.height="100%",a=o.firstChild.style,a.width=a.height="100%",e},activeMenu:function(e){var t=this;n.toggleClass(t.getEl().lastChild,t.classPrefix+"active",e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon?n+"ico "+n+"i-"+e.settings.icon:"";return'<div id="'+t+'" class="'+e.classes()+'">'+'<button type="button" hidefocus tabindex="-1">'+(r?'<i class="'+r+'"></i>':"")+(e._text?(r?" ":"")+e._text:"")+"</button>"+'<button type="button" class="'+n+'open" hidefocus tabindex="-1">'+(e._menuBtnText?(r?" ":"")+e._menuBtnText:"")+' <i class="'+n+'caret"></i>'+"</button>"+"</div>"},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(e){e.control!=this||n.getParent(e.target,"."+this.classPrefix+"open")||(e.stopImmediatePropagation(),t.call(this,e))}),delete e.settings.onclick,e._super()}})}),r(Gt,[Mt],function(e){return e.extend({Defaults:{containerClass:"stack-layout",controlClass:"stack-layout-item",endClass:"break"}})}),r(Yt,[K,z],function(e,t){"use stict";return e.extend({lastIdx:0,Defaults:{layout:"absolute",defaults:{type:"panel"}},activateTab:function(e){this.activeTabId&&t.removeClass(this.getEl(this.activeTabId),this.classPrefix+"active"),this.activeTabId="t"+e,t.addClass(this.getEl("t"+e),this.classPrefix+"active"),e!=this.lastIdx&&(this.items()[this.lastIdx].hide(),this.lastIdx=e),this.items()[e].show().fire("showtab"),this.reflow()},renderHtml:function(){var e=this,t=e._layout,n="",r=e.classPrefix;return e.preRender(),t.preRender(e),e.items().each(function(t,i){n+='<div id="'+e._id+"-t"+i+'" class="'+r+'tab" unselectable="on">'+e.encode(t.settings.title)+"</div>"}),'<div id="'+e._id+'" class="'+e.classes()+'" hideFocus="1" tabIndex="-1">'+'<div id="'+e._id+'-head" class="'+r+'tabs">'+n+"</div>"+'<div id="'+e._id+'-body" class="'+e.classes("body")+'">'+t.renderHtml(e)+"</div>"+"</div>"},postRender:function(){var e=this;e._super(),e.settings.activeTab=e.settings.activeTab||0,e.activateTab(e.settings.activeTab),this.on("click",function(t){var n=t.target.parentNode;if(t.target.parentNode.id==e._id+"-head")for(var r=n.childNodes.length;r--;)n.childNodes[r]==t.target&&e.activateTab(r)})},initLayoutRect:function(){var e=this,t,n,r;n=r=0,e.items().each(function(t,i){n=Math.max(n,t.layoutRect().minW),r=Math.max(r,t.layoutRect().minH),e.settings.activeTab!=i&&t.hide()}),e.items().each(function(e){e.settings.x=0,e.settings.y=0,e.settings.w=n,e.settings.h=r,e.layoutRect({x:0,y:0,w:n,h:r})});var i=e.getEl("head").offsetHeight;return e.settings.minWidth=n,e.settings.minHeight=r+i,t=e._super(),t.deltaH+=e.getEl("head").offsetHeight,t.innerH=t.h-t.deltaH,t}})}),r(Xt,[yt,z],function(e,t){return e.extend({init:function(e){var t=this;t._super(e),t._value=e.value||"",t.addClass("textbox"),e.multiline?t.addClass("multiline"):t.on("keydown",function(e){13==e.keyCode&&t.parents().reverse().each(function(t){return e.preventDefault(),t.submit?(t.submit(),!1):void 0})})},value:function(e){var t=this;return"undefined"!=typeof e?(t._value=e,t._rendered&&(t.getEl().value=e),t):t._rendered?t.getEl().value:t._value},repaint:function(){var e=this,t,n,r,i=0,o=0,a;t=e.getEl().style,n=e._layoutRect,a=e._lastRepaintRect||{};var s=document;return!e.settings.multiline&&s.all&&(!s.documentMode||s.documentMode<=8)&&(t.lineHeight=n.h-o+"px"),r=e._borderBox,i=r.left+r.right+8,o=r.top+r.bottom+(e.settings.multiline?8:0),n.x!==a.x&&(t.left=n.x+"px",a.x=n.x),n.y!==a.y&&(t.top=n.y+"px",a.y=n.y),n.w!==a.w&&(t.width=n.w-i+"px",a.w=n.w),n.h!==a.h&&(t.height=n.h-o+"px",a.h=n.h),e._lastRepaintRect=a,e.fire("repaint",{},!1),e},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.encode(e._value,!1),i="";return"spellcheck"in n&&(i+=' spellcheck="'+n.spellcheck+'"'),n.maxLength&&(i+=' maxlength="'+n.maxLength+'"'),n.size&&(i+=' size="'+n.size+'"'),n.subtype&&(i+=' type="'+n.subtype+'"'),n.multiline?'<textarea id="'+t+'" class="'+e.classes()+'" '+(n.rows?' rows="'+n.rows+'"':"")+' hidefocus="true"'+i+">"+r+"</textarea>":'<input id="'+t+'" class="'+e.classes()+'" value="'+r+'" hidefocus="true"'+i+">"},postRender:function(){var e=this;return t.on(e.getEl(),"change",function(t){e.fire("change",t)}),e._super()}})}),r(Jt,[z],function(e){return function(t){var n=this,r;n.show=function(i){return n.hide(),r=!0,window.setTimeout(function(){r&&t.appendChild(e.createFragment('<div class="mce-throbber"></div>'))},i||0),n},n.hide=function(){var e=t.lastChild;return e&&-1!=e.className.indexOf("throbber")&&e.parentNode.removeChild(e),r=!1,n}}}),a([l,c,u,d,f,p,h,m,g,v,y,b,C,x,w,_,N,E,S,k,T,R,A,B,L,M,D,H,P,O,I,F,W,z,V,U,q,$,j,K,G,Y,X,J,Q,Z,et,tt,nt,rt,it,ot,at,st,lt,ct,ut,dt,ft,pt,ht,mt,gt,vt,yt,bt,Ct,xt,wt,_t,Nt,Et,St,kt,Tt,Rt,At,Bt,Lt,Mt,Dt,Ht,Pt,Ot,It,Ft,Wt,zt,Vt,Ut,qt,$t,jt,Kt,Gt,Yt,Xt,Jt])}(this);
\ No newline at end of file diff --git a/extlib/video-js/LGPLv3-LICENSE.txt b/extlib/video-js/LGPLv3-LICENSE.txt deleted file mode 100644 index 65c5ca88..00000000 --- a/extlib/video-js/LGPLv3-LICENSE.txt +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/extlib/video-js/LICENSE b/extlib/video-js/LICENSE new file mode 100644 index 00000000..138a50e8 --- /dev/null +++ b/extlib/video-js/LICENSE @@ -0,0 +1,13 @@ +Copyright 2013 Brightcove, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
\ No newline at end of file diff --git a/extlib/video-js/demo.captions.vtt b/extlib/video-js/demo.captions.vtt new file mode 100644 index 00000000..e598be19 --- /dev/null +++ b/extlib/video-js/demo.captions.vtt @@ -0,0 +1,41 @@ +WEBVTT + +00:00.700 --> 00:04.110 +Captions describe all relevant audio for the hearing impaired. +[ Heroic music playing for a seagull ] + +00:04.500 --> 00:05.000 +[ Splash!!! ] + +00:05.100 --> 00:06.000 +[ Sploosh!!! ] + +00:08.000 --> 00:09.225 +[ Splash...splash...splash splash splash ] + +00:10.525 --> 00:11.255 +[ Splash, Sploosh again ] + +00:13.500 --> 00:14.984 +Dolphin: eeeEEEEEeeee! + +00:14.984 --> 00:16.984 +Dolphin: Squawk! eeeEEE? + +00:25.000 --> 00:28.284 +[ A whole ton of splashes ] + +00:29.500 --> 00:31.000 +Mine. Mine. Mine. + +00:34.300 --> 00:36.000 +Shark: Chomp + +00:36.800 --> 00:37.900 +Shark: CHOMP!!! + +00:37.861 --> 00:41.193 +EEEEEEOOOOOOOOOOWHALENOISE + +00:42.593 --> 00:45.611 +[ BIG SPLASH ]
\ No newline at end of file diff --git a/extlib/video-js/demo.html b/extlib/video-js/demo.html new file mode 100644 index 00000000..fb26a087 --- /dev/null +++ b/extlib/video-js/demo.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html> +<head> + <title>Video.js | HTML5 Video Player</title> + + <!-- Chang URLs to wherever Video.js files will be hosted --> + <link href="video-js.css" rel="stylesheet" type="text/css"> + <!-- video.js must be in the <head> for older IEs to work. --> + <script src="video.js"></script> + + <!-- Unless using the CDN hosted version, update the URL to the Flash SWF --> + <script> + videojs.options.flash.swf = "video-js.swf"; + </script> + + +</head> +<body> + + <video id="example_video_1" class="video-js vjs-default-skin" controls preload="none" width="640" height="264" + poster="http://video-js.zencoder.com/oceans-clip.png" + data-setup="{}"> + <source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' /> + <source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm' /> + <source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg' /> + <track kind="captions" src="demo.captions.vtt" srclang="en" label="English"></track><!-- Tracks need an ending tag thanks to IE9 --> + </video> + +</body> +</html> diff --git a/extlib/video-js/font/vjs.eot b/extlib/video-js/font/vjs.eot Binary files differnew file mode 100644 index 00000000..1b8202af --- /dev/null +++ b/extlib/video-js/font/vjs.eot diff --git a/extlib/video-js/font/vjs.svg b/extlib/video-js/font/vjs.svg new file mode 100644 index 00000000..2059a1f2 --- /dev/null +++ b/extlib/video-js/font/vjs.svg @@ -0,0 +1,40 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata> +This is a custom SVG font generated by IcoMoon. +<iconset grid="16"></iconset> +</metadata> +<defs> +<font id="VideoJS" horiz-adv-x="512" > +<font-face units-per-em="512" ascent="480" descent="-32" /> +<missing-glyph horiz-adv-x="512" /> +<glyph unicode="" d="M 512.00,480.00 L 512.00,272.00 L 432.00,352.00 L 336.00,256.00 L 288.00,304.00 L 384.00,400.00 L 304.00,480.00 ZM 224.00,144.00 L 128.00,48.00 L 208.00-32.00 L 0.00-32.00 L 0.00,176.00 L 80.00,96.00 L 176.00,192.00 Z" /> +<glyph unicode="" d="M 96.00,416.00L 416.00,224.00L 96.00,32.00 z" /> +<glyph unicode="" d="M 64.00,416.00L 224.00,416.00L 224.00,32.00L 64.00,32.00zM 288.00,416.00L 448.00,416.00L 448.00,32.00L 288.00,32.00z" /> +<glyph unicode="" d="M 200.666,440.666 C 213.50,453.50 224.00,449.15 224.00,431.00 L 224.00,17.00 C 224.00-1.15 213.50-5.499 200.666,7.335 L 80.00,128.00 L 0.00,128.00 L 0.00,320.00 L 80.00,320.00 L 200.666,440.666 Z" /> +<glyph unicode="" d="M 274.51,109.49c-6.143,0.00-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0.00,33.941 + c 40.55,40.55, 40.55,106.529,0.00,147.078c-9.373,9.373-9.373,24.569,0.00,33.941c 9.373,9.372, 24.568,9.372, 33.941,0.00 + c 59.265-59.265, 59.265-155.696,0.00-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.50,453.50 224.00,449.15 224.00,431.00 L 224.00,17.00 C 224.00-1.15 213.50-5.499 200.666,7.335 L 80.00,128.00 L 0.00,128.00 L 0.00,320.00 L 80.00,320.00 L 200.666,440.666 Z" /> +<glyph unicode="" d="M 359.765,64.235c-6.143,0.00-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0.00,33.941 + c 65.503,65.503, 65.503,172.085,0.00,237.588c-9.372,9.373-9.372,24.569,0.00,33.941c 9.372,9.371, 24.569,9.372, 33.941,0.00 + C 417.532,335.938, 440.00,281.696, 440.00,224.00c0.00-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0.00-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0.00,33.941 + c 40.55,40.55, 40.55,106.529,0.00,147.078c-9.373,9.373-9.373,24.569,0.00,33.941c 9.373,9.372, 24.568,9.372, 33.941,0.00 + c 59.265-59.265, 59.265-155.696,0.00-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.50,453.50 224.00,449.15 224.00,431.00 L 224.00,17.00 C 224.00-1.15 213.50-5.499 200.666,7.335 L 80.00,128.00 L 0.00,128.00 L 0.00,320.00 L 80.00,320.00 L 200.666,440.666 Z" /> +<glyph unicode="" d="M 445.02,18.98c-6.143,0.00-12.284,2.343-16.971,7.029c-9.372,9.373-9.372,24.568,0.00,33.941 + C 471.868,103.771, 496.001,162.03, 496.001,224.00c0.00,61.969-24.133,120.229-67.952,164.049c-9.372,9.373-9.372,24.569,0.00,33.941 + c 9.372,9.372, 24.569,9.372, 33.941,0.00c 52.885-52.886, 82.011-123.20, 82.011-197.99c0.00-74.791-29.126-145.104-82.011-197.99 + C 457.304,21.323, 451.162,18.98, 445.02,18.98zM 359.765,64.235c-6.143,0.00-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0.00,33.941 + c 65.503,65.503, 65.503,172.085,0.00,237.588c-9.372,9.373-9.372,24.569,0.00,33.941c 9.372,9.371, 24.569,9.372, 33.941,0.00 + C 417.532,335.938, 440.00,281.696, 440.00,224.00c0.00-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0.00-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0.00,33.941 + c 40.55,40.55, 40.55,106.529,0.00,147.078c-9.373,9.373-9.373,24.569,0.00,33.941c 9.373,9.372, 24.568,9.372, 33.941,0.00 + c 59.265-59.265, 59.265-155.696,0.00-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.50,453.50 224.00,449.15 224.00,431.00 L 224.00,17.00 C 224.00-1.15 213.50-5.499 200.666,7.335 L 80.00,128.00 L 0.00,128.00 L 0.00,320.00 L 80.00,320.00 L 200.666,440.666 Z" horiz-adv-x="544" /> +<glyph unicode="" d="M 256.00,480.00L 96.00,224.00L 256.00-32.00L 416.00,224.00 z" /> +<glyph unicode="" d="M 0.00,480.00 L 687.158,480.00 L 687.158-35.207 L 0.00-35.207 L 0.00,480.00 z M 622.731,224.638 C 621.878,314.664 618.46,353.922 597.131,381.656 C 593.291,387.629 586.038,391.042 580.065,395.304 C 559.158,410.669 460.593,416.211 346.247,416.211 C 231.896,416.211 128.642,410.669 108.162,395.304 C 101.762,391.042 94.504,387.629 90.242,381.656 C 69.331,353.922 66.349,314.664 65.069,224.638 C 66.349,134.607 69.331,95.353 90.242,67.62 C 94.504,61.22 101.762,58.233 108.162,53.967 C 128.642,38.18 231.896,33.06 346.247,32.207 C 460.593,33.06 559.158,38.18 580.065,53.967 C 586.038,58.233 593.291,61.22 597.131,67.62 C 618.46,95.353 621.878,134.607 622.731,224.638 z M 331.179,247.952 C 325.389,318.401 287.924,359.905 220.901,359.905 C 159.672,359.905 111.54,304.689 111.54,215.965 C 111.54,126.859 155.405,71.267 227.907,71.267 C 285.79,71.267 326.306,113.916 332.701,184.742 L 263.55,184.742 C 260.81,158.468 249.843,138.285 226.69,138.285 C 190.136,138.285 183.435,174.462 183.435,212.92 C 183.435,265.854 198.665,292.886 223.951,292.886 C 246.492,292.886 260.81,276.511 262.939,247.952 L 331.179,247.952 z M 570.013,247.952 C 564.228,318.401 526.758,359.905 459.74,359.905 C 398.507,359.905 350.379,304.689 350.379,215.965 C 350.379,126.859 394.244,71.267 466.746,71.267 C 524.625,71.267 565.14,113.916 571.536,184.742 L 502.384,184.742 C 499.649,158.468 488.682,138.285 465.529,138.285 C 428.971,138.285 422.27,174.462 422.27,212.92 C 422.27,265.854 437.504,292.886 462.785,292.886 C 485.327,292.886 499.649,276.511 501.778,247.952 L 570.013,247.952 z " horiz-adv-x="687.1578947368421" /> +<glyph unicode="" d="M 64.00,416.00L 448.00,416.00L 448.00,32.00L 64.00,32.00z" /> +<glyph unicode="" d="M 192.00,416.00A64.00,64.00 12780.00 1 1 320.00,416A64.00,64.00 12780.00 1 1 192.00,416zM 327.765,359.765A64.00,64.00 12780.00 1 1 455.765,359.765A64.00,64.00 12780.00 1 1 327.765,359.765zM 416.00,224.00A32.00,32.00 12780.00 1 1 480.00,224A32.00,32.00 12780.00 1 1 416.00,224zM 359.765,88.235A32.00,32.00 12780.00 1 1 423.765,88.23500000000001A32.00,32.00 12780.00 1 1 359.765,88.23500000000001zM 224.001,32.00A32.00,32.00 12780.00 1 1 288.001,32A32.00,32.00 12780.00 1 1 224.001,32zM 88.236,88.235A32.00,32.00 12780.00 1 1 152.236,88.23500000000001A32.00,32.00 12780.00 1 1 88.236,88.23500000000001zM 72.236,359.765A48.00,48.00 12780.00 1 1 168.236,359.765A48.00,48.00 12780.00 1 1 72.236,359.765zM 28.00,224.00A36.00,36.00 12780.00 1 1 100.00,224A36.00,36.00 12780.00 1 1 28.00,224z" /> +<glyph unicode="" d="M 224.00,192.00 L 224.00-16.00 L 144.00,64.00 L 48.00-32.00 L 0.00,16.00 L 96.00,112.00 L 16.00,192.00 ZM 512.00,432.00 L 416.00,336.00 L 496.00,256.00 L 288.00,256.00 L 288.00,464.00 L 368.00,384.00 L 464.00,480.00 Z" /> +<glyph unicode="" d="M 256.00,448.00 C 397.385,448.00 512.00,354.875 512.00,240.00 C 512.00,125.124 397.385,32.00 256.00,32.00 C 242.422,32.00 229.095,32.867 216.088,34.522 C 161.099-20.467 95.463-30.328 32.00-31.776 L 32.00-18.318 C 66.268-1.529 96.00,29.052 96.00,64.00 C 96.00,68.877 95.621,73.665 94.918,78.348 C 37.02,116.48 0.00,174.725 0.00,240.00 C 0.00,354.875 114.615,448.00 256.00,448.00 Z" /> +<glyph unicode=" " horiz-adv-x="256" /> +<glyph class="hidden" unicode="" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" /> +</font></defs></svg>
\ No newline at end of file diff --git a/extlib/video-js/font/vjs.ttf b/extlib/video-js/font/vjs.ttf Binary files differnew file mode 100644 index 00000000..a5ad4685 --- /dev/null +++ b/extlib/video-js/font/vjs.ttf diff --git a/extlib/video-js/font/vjs.woff b/extlib/video-js/font/vjs.woff Binary files differnew file mode 100644 index 00000000..375510e0 --- /dev/null +++ b/extlib/video-js/font/vjs.woff diff --git a/extlib/video-js/video-js.css b/extlib/video-js/video-js.css new file mode 100644 index 00000000..11435c32 --- /dev/null +++ b/extlib/video-js/video-js.css @@ -0,0 +1,757 @@ +/*! +Video.js Default Styles (http://videojs.com) +Version 4.2.1 +Create your own skin at http://designer.videojs.com +*/ +/* SKIN +================================================================================ +The main class name for all skin-specific styles. To make your own skin, +replace all occurances of 'vjs-default-skin' with a new name. Then add your new +skin name to your video tag instead of the default skin. +e.g. <video class="video-js my-skin-name"> +*/ +.vjs-default-skin { + color: #cccccc; +} +/* Custom Icon Font +-------------------------------------------------------------------------------- +The control icons are from a custom font. Each icon corresponds to a character +(e.g. "\e001"). Font icons allow for easy scaling and coloring of icons. +*/ +@font-face { + font-family: 'VideoJS'; + src: url('font/vjs.eot'); + src: url('font/vjs.eot?#iefix') format('embedded-opentype'), url('font/vjs.woff') format('woff'), url('font/vjs.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} +/* Base UI Component Classes +-------------------------------------------------------------------------------- +*/ +/* Slider - used for Volume bar and Seek bar */ +.vjs-default-skin .vjs-slider { + /* Replace browser focus hightlight with handle highlight */ + outline: 0; + position: relative; + cursor: pointer; + padding: 0; + /* background-color-with-alpha */ + background-color: #333333; + background-color: rgba(51, 51, 51, 0.9); +} +.vjs-default-skin .vjs-slider:focus { + /* box-shadow */ + -webkit-box-shadow: 0 0 2em #ffffff; + -moz-box-shadow: 0 0 2em #ffffff; + box-shadow: 0 0 2em #ffffff; +} +.vjs-default-skin .vjs-slider-handle { + position: absolute; + /* Needed for IE6 */ + left: 0; + top: 0; +} +.vjs-default-skin .vjs-slider-handle:before { + content: "\e009"; + font-family: VideoJS; + font-size: 1em; + line-height: 1; + text-align: center; + text-shadow: 0em 0em 1em #fff; + position: absolute; + top: 0; + left: 0; + /* Rotate the square icon to make a diamond */ + /* transform */ + -webkit-transform: rotate(-45deg); + -moz-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + -o-transform: rotate(-45deg); + transform: rotate(-45deg); +} +/* Control Bar +-------------------------------------------------------------------------------- +The default control bar that is a container for most of the controls. +*/ +.vjs-default-skin .vjs-control-bar { + /* Start hidden */ + display: none; + position: absolute; + /* Place control bar at the bottom of the player box/video. + If you want more margin below the control bar, add more height. */ + bottom: 0; + /* Use left/right to stretch to 100% width of player div */ + left: 0; + right: 0; + /* Height includes any margin you want above or below control items */ + height: 3.0em; + /* background-color-with-alpha */ + background-color: #07141e; + background-color: rgba(7, 20, 30, 0.7); +} +/* Show the control bar only once the video has started playing */ +.vjs-default-skin.vjs-has-started .vjs-control-bar { + display: block; + /* Visibility needed to make sure things hide in older browsers too. */ + + visibility: visible; + opacity: 1; + /* transition */ + -webkit-transition: visibility 0.1s, opacity 0.1s; + -moz-transition: visibility 0.1s, opacity 0.1s; + -o-transition: visibility 0.1s, opacity 0.1s; + transition: visibility 0.1s, opacity 0.1s; +} +/* Hide the control bar when the video is playing and the user is inactive */ +.vjs-default-skin.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar { + display: block; + visibility: hidden; + opacity: 0; + /* transition */ + -webkit-transition: visibility 1s, opacity 1s; + -moz-transition: visibility 1s, opacity 1s; + -o-transition: visibility 1s, opacity 1s; + transition: visibility 1s, opacity 1s; +} +.vjs-default-skin.vjs-controls-disabled .vjs-control-bar { + display: none; +} +.vjs-default-skin.vjs-using-native-controls .vjs-control-bar { + display: none; +} +/* IE8 is flakey with fonts, and you have to change the actual content to force +fonts to show/hide properly. + - "\9" IE8 hack didn't work for this + - Found in XP IE8 from http://modern.ie. Does not show up in "IE8 mode" in IE9 +*/ +@media \0screen { + .vjs-default-skin.vjs-user-inactive.vjs-playing .vjs-control-bar :before { + content: ""; + } +} +/* General styles for individual controls. */ +.vjs-default-skin .vjs-control { + outline: none; + position: relative; + float: left; + text-align: center; + margin: 0; + padding: 0; + height: 3.0em; + width: 4em; +} +/* FontAwsome button icons */ +.vjs-default-skin .vjs-control:before { + font-family: VideoJS; + font-size: 1.5em; + line-height: 2; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-align: center; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5); +} +/* Replacement for focus outline */ +.vjs-default-skin .vjs-control:focus:before, +.vjs-default-skin .vjs-control:hover:before { + text-shadow: 0em 0em 1em #ffffff; +} +.vjs-default-skin .vjs-control:focus { + /* outline: 0; */ + /* keyboard-only users cannot see the focus on several of the UI elements when + this is set to 0 */ + +} +/* Hide control text visually, but have it available for screenreaders */ +.vjs-default-skin .vjs-control-text { + /* hide-visually */ + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +/* Play/Pause +-------------------------------------------------------------------------------- +*/ +.vjs-default-skin .vjs-play-control { + width: 5em; + cursor: pointer; +} +.vjs-default-skin .vjs-play-control:before { + content: "\e001"; +} +.vjs-default-skin.vjs-playing .vjs-play-control:before { + content: "\e002"; +} +/* Volume/Mute +-------------------------------------------------------------------------------- */ +.vjs-default-skin .vjs-mute-control, +.vjs-default-skin .vjs-volume-menu-button { + cursor: pointer; + float: right; +} +.vjs-default-skin .vjs-mute-control:before, +.vjs-default-skin .vjs-volume-menu-button:before { + content: "\e006"; +} +.vjs-default-skin .vjs-mute-control.vjs-vol-0:before, +.vjs-default-skin .vjs-volume-menu-button.vjs-vol-0:before { + content: "\e003"; +} +.vjs-default-skin .vjs-mute-control.vjs-vol-1:before, +.vjs-default-skin .vjs-volume-menu-button.vjs-vol-1:before { + content: "\e004"; +} +.vjs-default-skin .vjs-mute-control.vjs-vol-2:before, +.vjs-default-skin .vjs-volume-menu-button.vjs-vol-2:before { + content: "\e005"; +} +.vjs-default-skin .vjs-volume-control { + width: 5em; + float: right; +} +.vjs-default-skin .vjs-volume-bar { + width: 5em; + height: 0.6em; + margin: 1.1em auto 0; +} +.vjs-default-skin .vjs-volume-menu-button .vjs-menu-content { + height: 2.9em; +} +.vjs-default-skin .vjs-volume-level { + position: absolute; + top: 0; + left: 0; + height: 0.5em; + background: #66a8cc url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAP0lEQVQIHWWMAQoAIAgDR/QJ/Ub//04+w7ZICBwcOg5FZi5iBB82AGzixEglJrd4TVK5XUJpskSTEvpdFzX9AB2pGziSQcvAAAAAAElFTkSuQmCC) -50% 0 repeat; +} +.vjs-default-skin .vjs-volume-bar .vjs-volume-handle { + width: 0.5em; + height: 0.5em; +} +.vjs-default-skin .vjs-volume-handle:before { + font-size: 0.9em; + top: -0.2em; + left: -0.2em; + width: 1em; + height: 1em; +} +.vjs-default-skin .vjs-volume-menu-button .vjs-menu .vjs-menu-content { + width: 6em; + left: -4em; +} +/* Progress +-------------------------------------------------------------------------------- +*/ +.vjs-default-skin .vjs-progress-control { + position: absolute; + left: 0; + right: 0; + width: auto; + font-size: 0.3em; + height: 1em; + /* Set above the rest of the controls. */ + top: -1em; + /* Shrink the bar slower than it grows. */ + /* transition */ + -webkit-transition: all 0.4s; + -moz-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; +} +/* On hover, make the progress bar grow to something that's more clickable. + This simply changes the overall font for the progress bar, and this + updates both the em-based widths and heights, as wells as the icon font */ +.vjs-default-skin:hover .vjs-progress-control { + font-size: .9em; + /* Even though we're not changing the top/height, we need to include them in + the transition so they're handled correctly. */ + + /* transition */ + -webkit-transition: all 0.2s; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + transition: all 0.2s; +} +/* Box containing play and load progresses. Also acts as seek scrubber. */ +.vjs-default-skin .vjs-progress-holder { + height: 100%; +} +/* Progress Bars */ +.vjs-default-skin .vjs-progress-holder .vjs-play-progress, +.vjs-default-skin .vjs-progress-holder .vjs-load-progress { + position: absolute; + display: block; + height: 100%; + margin: 0; + padding: 0; + /* Needed for IE6 */ + left: 0; + top: 0; +} +.vjs-default-skin .vjs-play-progress { + /* + Using a data URI to create the white diagonal lines with a transparent + background. Surprisingly works in IE8. + Created using http://www.patternify.com + Changing the first color value will change the bar color. + Also using a paralax effect to make the lines move backwards. + The -50% left position makes that happen. + */ + + background: #66a8cc url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAP0lEQVQIHWWMAQoAIAgDR/QJ/Ub//04+w7ZICBwcOg5FZi5iBB82AGzixEglJrd4TVK5XUJpskSTEvpdFzX9AB2pGziSQcvAAAAAAElFTkSuQmCC) -50% 0 repeat; +} +.vjs-default-skin .vjs-load-progress { + background: #646464 /* IE8- Fallback */; + background: rgba(255, 255, 255, 0.4); +} +.vjs-default-skin .vjs-seek-handle { + width: 1.5em; + height: 100%; +} +.vjs-default-skin .vjs-seek-handle:before { + padding-top: 0.1em /* Minor adjustment */; +} +/* Time Display +-------------------------------------------------------------------------------- +*/ +.vjs-default-skin .vjs-time-controls { + font-size: 1em; + /* Align vertically by making the line height the same as the control bar */ + line-height: 3em; +} +.vjs-default-skin .vjs-current-time { + float: left; +} +.vjs-default-skin .vjs-duration { + float: left; +} +/* Remaining time is in the HTML, but not included in default design */ +.vjs-default-skin .vjs-remaining-time { + display: none; + float: left; +} +.vjs-time-divider { + float: left; + line-height: 3em; +} +/* Fullscreen +-------------------------------------------------------------------------------- +*/ +.vjs-default-skin .vjs-fullscreen-control { + width: 3.8em; + cursor: pointer; + float: right; +} +.vjs-default-skin .vjs-fullscreen-control:before { + content: "\e000"; +} +/* Switch to the exit icon when the player is in fullscreen */ +.vjs-default-skin.vjs-fullscreen .vjs-fullscreen-control:before { + content: "\e00b"; +} +/* Big Play Button (play button at start) +-------------------------------------------------------------------------------- +Positioning of the play button in the center or other corners can be done more +easily in the skin designer. http://designer.videojs.com/ +*/ +.vjs-default-skin .vjs-big-play-button { + left: 0.5em; + top: 0.5em; + font-size: 3em; + display: block; + z-index: 2; + position: absolute; + width: 4em; + height: 2.6em; + text-align: center; + vertical-align: middle; + cursor: pointer; + opacity: 1; + /* Need a slightly gray bg so it can be seen on black backgrounds */ + /* background-color-with-alpha */ + background-color: #07141e; + background-color: rgba(7, 20, 30, 0.7); + border: 0.1em solid #3b4249; + /* border-radius */ + -webkit-border-radius: 0.8em; + -moz-border-radius: 0.8em; + border-radius: 0.8em; + /* box-shadow */ + -webkit-box-shadow: 0px 0px 1em rgba(255, 255, 255, 0.25); + -moz-box-shadow: 0px 0px 1em rgba(255, 255, 255, 0.25); + box-shadow: 0px 0px 1em rgba(255, 255, 255, 0.25); + /* transition */ + -webkit-transition: all 0.4s; + -moz-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; +} +/* Hide if controls are disabled */ +.vjs-default-skin.vjs-controls-disabled .vjs-big-play-button { + display: none; +} +/* Hide when video starts playing */ +.vjs-default-skin.vjs-has-started .vjs-big-play-button { + display: none; +} +/* Hide on mobile devices. Remove when we stop using native controls + by default on mobile */ +.vjs-default-skin.vjs-using-native-controls .vjs-big-play-button { + display: none; +} +.vjs-default-skin:hover .vjs-big-play-button, +.vjs-default-skin .vjs-big-play-button:focus { + outline: 0; + border-color: #fff; + /* IE8 needs a non-glow hover state */ + background-color: #505050; + background-color: rgba(50, 50, 50, 0.75); + /* box-shadow */ + -webkit-box-shadow: 0 0 3em #ffffff; + -moz-box-shadow: 0 0 3em #ffffff; + box-shadow: 0 0 3em #ffffff; + /* transition */ + -webkit-transition: all 0s; + -moz-transition: all 0s; + -o-transition: all 0s; + transition: all 0s; +} +.vjs-default-skin .vjs-big-play-button:before { + content: "\e001"; + font-family: VideoJS; + /* In order to center the play icon vertically we need to set the line height + to the same as the button height */ + + line-height: 2.6em; + text-shadow: 0.05em 0.05em 0.1em #000; + text-align: center /* Needed for IE8 */; + position: absolute; + left: 0; + width: 100%; + height: 100%; +} +/* Loading Spinner +-------------------------------------------------------------------------------- +*/ +.vjs-loading-spinner { + display: none; + position: absolute; + top: 50%; + left: 50%; + font-size: 5em; + line-height: 1; + width: 1em; + height: 1em; + margin-left: -0.5em; + margin-top: -0.5em; + opacity: 0.75; + /* animation */ + -webkit-animation: spin 1.5s infinite linear; + -moz-animation: spin 1.5s infinite linear; + -o-animation: spin 1.5s infinite linear; + animation: spin 1.5s infinite linear; +} +.vjs-default-skin .vjs-loading-spinner:before { + content: "\e00a"; + font-family: VideoJS; + position: absolute; + top: 0; + left: 0; + width: 1em; + height: 1em; + text-align: center; + text-shadow: 0em 0em 0.1em #000; +} +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + } + 100% { + -moz-transform: rotate(359deg); + } +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + } +} +@-o-keyframes spin { + 0% { + -o-transform: rotate(0deg); + } + 100% { + -o-transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} +/* Menu Buttons (Captions/Subtitles/etc.) +-------------------------------------------------------------------------------- +*/ +.vjs-default-skin .vjs-menu-button { + float: right; + cursor: pointer; +} +.vjs-default-skin .vjs-menu { + display: none; + position: absolute; + bottom: 0; + left: 0em; + /* (Width of vjs-menu - width of button) / 2 */ + + width: 0em; + height: 0em; + margin-bottom: 3em; + border-left: 2em solid transparent; + border-right: 2em solid transparent; + border-top: 1.55em solid #000000; + /* Same width top as ul bottom */ + + border-top-color: rgba(7, 40, 50, 0.5); + /* Same as ul background */ + +} +/* Button Pop-up Menu */ +.vjs-default-skin .vjs-menu-button .vjs-menu .vjs-menu-content { + display: block; + padding: 0; + margin: 0; + position: absolute; + width: 10em; + bottom: 1.5em; + /* Same bottom as vjs-menu border-top */ + + max-height: 15em; + overflow: auto; + left: -5em; + /* Width of menu - width of button / 2 */ + + /* background-color-with-alpha */ + background-color: #07141e; + background-color: rgba(7, 20, 30, 0.7); + /* box-shadow */ + -webkit-box-shadow: -0.2em -0.2em 0.3em rgba(255, 255, 255, 0.2); + -moz-box-shadow: -0.2em -0.2em 0.3em rgba(255, 255, 255, 0.2); + box-shadow: -0.2em -0.2em 0.3em rgba(255, 255, 255, 0.2); +} +.vjs-default-skin .vjs-menu-button:hover .vjs-menu { + display: block; +} +.vjs-default-skin .vjs-menu-button ul li { + list-style: none; + margin: 0; + padding: 0.3em 0 0.3em 0; + line-height: 1.4em; + font-size: 1.2em; + text-align: center; + text-transform: lowercase; +} +.vjs-default-skin .vjs-menu-button ul li.vjs-selected { + background-color: #000; +} +.vjs-default-skin .vjs-menu-button ul li:focus, +.vjs-default-skin .vjs-menu-button ul li:hover, +.vjs-default-skin .vjs-menu-button ul li.vjs-selected:focus, +.vjs-default-skin .vjs-menu-button ul li.vjs-selected:hover { + outline: 0; + color: #111; + /* background-color-with-alpha */ + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.75); + /* box-shadow */ + -webkit-box-shadow: 0 0 1em #ffffff; + -moz-box-shadow: 0 0 1em #ffffff; + box-shadow: 0 0 1em #ffffff; +} +.vjs-default-skin .vjs-menu-button ul li.vjs-menu-title { + text-align: center; + text-transform: uppercase; + font-size: 1em; + line-height: 2em; + padding: 0; + margin: 0 0 0.3em 0; + font-weight: bold; + cursor: default; +} +/* Subtitles Button */ +.vjs-default-skin .vjs-subtitles-button:before { + content: "\e00c"; +} +/* Captions Button */ +.vjs-default-skin .vjs-captions-button:before { + content: "\e008"; +} +/* Replacement for focus outline */ +.vjs-default-skin .vjs-captions-button:focus .vjs-control-content:before, +.vjs-default-skin .vjs-captions-button:hover .vjs-control-content:before { + /* box-shadow */ + -webkit-box-shadow: 0 0 1em #ffffff; + -moz-box-shadow: 0 0 1em #ffffff; + box-shadow: 0 0 1em #ffffff; +} +/* +REQUIRED STYLES (be careful overriding) +================================================================================ +When loading the player, the video tag is replaced with a DIV, +that will hold the video tag or object tag for other playback methods. +The div contains the video playback element (Flash or HTML5) and controls, +and sets the width and height of the video. + +** If you want to add some kind of border/padding (e.g. a frame), or special +positioning, use another containing element. Otherwise you risk messing up +control positioning and full window mode. ** +*/ +.video-js { + background-color: #000; + position: relative; + padding: 0; + /* Start with 10px for base font size so other dimensions can be em based and + easily calculable. */ + + font-size: 10px; + /* Allow poster to be vertially aligned. */ + + vertical-align: middle; + /* display: table-cell; */ + /*This works in Safari but not Firefox.*/ + + /* Provide some basic defaults for fonts */ + + font-weight: normal; + font-style: normal; + /* Avoiding helvetica: issue #376 */ + + font-family: Arial, sans-serif; + /* Turn off user selection (text highlighting) by default. + The majority of player components will not be text blocks. + Text areas will need to turn user selection back on. */ + + /* user-select */ + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +/* Playback technology elements expand to the width/height of the containing div + <video> or <object> */ +.video-js .vjs-tech { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +/* Fix for Firefox 9 fullscreen (only if it is enabled). Not needed when + checking fullScreenEnabled. */ +.video-js:-moz-full-screen { + position: absolute; +} +/* Fullscreen Styles */ +body.vjs-full-window { + padding: 0; + margin: 0; + height: 100%; + /* Fix for IE6 full-window. http://www.cssplay.co.uk/layouts/fixed.html */ + overflow-y: auto; +} +.video-js.vjs-fullscreen { + position: fixed; + overflow: hidden; + z-index: 1000; + left: 0; + top: 0; + bottom: 0; + right: 0; + width: 100% !important; + height: 100% !important; + /* IE6 full-window (underscore hack) */ + _position: absolute; +} +.video-js:-webkit-full-screen { + width: 100% !important; + height: 100% !important; +} +.video-js.vjs-fullscreen.vjs-user-inactive { + cursor: none; +} +/* Poster Styles */ +.vjs-poster { + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain; + cursor: pointer; + height: 100%; + margin: 0; + padding: 0; + position: relative; + width: 100%; +} +.vjs-poster img { + display: block; + margin: 0 auto; + max-height: 100%; + padding: 0; + width: 100%; +} +/* Hide the poster when native controls are used otherwise it covers them */ +.video-js.vjs-using-native-controls .vjs-poster { + display: none; +} +/* Text Track Styles */ +/* Overall track holder for both captions and subtitles */ +.video-js .vjs-text-track-display { + text-align: center; + position: absolute; + bottom: 4em; + /* Leave padding on left and right */ + left: 1em; + right: 1em; +} +/* Individual tracks */ +.video-js .vjs-text-track { + display: none; + font-size: 1.4em; + text-align: center; + margin-bottom: 0.1em; + /* Transparent black background, or fallback to all black (oldIE) */ + /* background-color-with-alpha */ + background-color: #000000; + background-color: rgba(0, 0, 0, 0.5); +} +.video-js .vjs-subtitles { + color: #ffffff /* Subtitles are white */; +} +.video-js .vjs-captions { + color: #ffcc66 /* Captions are yellow */; +} +.vjs-tt-cue { + display: block; +} +/* Hide disabled or unsupported controls */ +.vjs-default-skin .vjs-hidden { + display: none; +} +.vjs-lock-showing { + display: block !important; + opacity: 1; + visibility: visible; +} +/* ----------------------------------------------------------------------------- +The original source of this file lives at +https://github.com/videojs/video.js/blob/master/src/css/video-js.less */ diff --git a/extlib/video-js/video-js.min.css b/extlib/video-js/video-js.min.css index 06c0e6b4..07bde6ee 100644 --- a/extlib/video-js/video-js.min.css +++ b/extlib/video-js/video-js.min.css @@ -1 +1,5 @@ -.video-js{background-color:#000;position:relative;padding:0;font-size:10px;vertical-align:middle}.video-js .vjs-tech{position:absolute;top:0;left:0;width:100%;height:100%}.video-js:-moz-full-screen{position:absolute}body.vjs-full-window{padding:0;margin:0;height:100%;overflow-y:auto}.video-js.vjs-fullscreen{position:fixed;overflow:hidden;z-index:1000;left:0;top:0;bottom:0;right:0;width:100%!important;height:100%!important;_position:absolute}.video-js:-webkit-full-screen{width:100%!important;height:100%!important}.vjs-poster{margin:0 auto;padding:0;cursor:pointer;position:relative;width:100%;max-height:100%}.video-js .vjs-text-track-display{text-align:center;position:absolute;bottom:4em;left:1em;right:1em;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.video-js .vjs-text-track{display:none;color:#fff;font-size:1.4em;text-align:center;margin-bottom:.1em;background:#000;background:rgba(0,0,0,0.50)}.video-js .vjs-subtitles{color:#fff}.video-js .vjs-captions{color:#fc6}.vjs-tt-cue{display:block}.vjs-fade-in{visibility:visible!important;opacity:1!important;-webkit-transition:visibility 0s linear 0s,opacity .3s linear;-moz-transition:visibility 0s linear 0s,opacity .3s linear;-ms-transition:visibility 0s linear 0s,opacity .3s linear;-o-transition:visibility 0s linear 0s,opacity .3s linear;transition:visibility 0s linear 0s,opacity .3s linear}.vjs-fade-out{visibility:hidden!important;opacity:0!important;-webkit-transition:visibility 0s linear 1.5s,opacity 1.5s linear;-moz-transition:visibility 0s linear 1.5s,opacity 1.5s linear;-ms-transition:visibility 0s linear 1.5s,opacity 1.5s linear;-o-transition:visibility 0s linear 1.5s,opacity 1.5s linear;transition:visibility 0s linear 1.5s,opacity 1.5s linear}.vjs-default-skin .vjs-controls{position:absolute;bottom:0;left:0;right:0;margin:0;padding:0;height:2.6em;color:#fff;border-top:1px solid #404040;background:#242424;background:-moz-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(50%,#242424),color-stop(50%,#1f1f1f),color-stop(100%,#171717));background:-webkit-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:-o-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:-ms-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);visibility:hidden;opacity:0}.vjs-default-skin .vjs-control{position:relative;float:left;text-align:center;margin:0;padding:0;height:2.6em;width:2.6em}.vjs-default-skin .vjs-control:focus{outline:0}.vjs-default-skin .vjs-control-text{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.vjs-default-skin .vjs-play-control{width:5em;cursor:pointer!important}.vjs-default-skin.vjs-paused .vjs-play-control div{width:15px;height:17px;background:url('video-js.png');margin:.5em auto 0}.vjs-default-skin.vjs-playing .vjs-play-control div{width:15px;height:17px;background:url('video-js.png') -25px 0;margin:.5em auto 0}.vjs-default-skin .vjs-rewind-control{width:5em;cursor:pointer!important}.vjs-default-skin .vjs-rewind-control div{width:19px;height:16px;background:url('video-js.png');margin:.5em auto 0}.vjs-default-skin .vjs-mute-control{width:3.8em;cursor:pointer!important;float:right}.vjs-default-skin .vjs-mute-control div{width:22px;height:16px;background:url('video-js.png') -75px -25px;margin:.5em auto 0}.vjs-default-skin .vjs-mute-control.vjs-vol-0 div{background:url('video-js.png') 0 -25px}.vjs-default-skin .vjs-mute-control.vjs-vol-1 div{background:url('video-js.png') -25px -25px}.vjs-default-skin .vjs-mute-control.vjs-vol-2 div{background:url('video-js.png') -50px -25px}.vjs-default-skin .vjs-volume-control{width:5em;float:right}.vjs-default-skin .vjs-volume-bar{position:relative;width:5em;height:.6em;margin:1em auto 0;cursor:pointer!important;-moz-border-radius:.3em;-webkit-border-radius:.3em;border-radius:.3em;background:#666;background:-moz-linear-gradient(top,#333,#666);background:-webkit-gradient(linear,0% 0,0% 100%,from(#333),to(#666));background:-webkit-linear-gradient(top,#333,#666);background:-o-linear-gradient(top,#333,#666);background:-ms-linear-gradient(top,#333,#666);background:linear-gradient(top,#333,#666)}.vjs-default-skin .vjs-volume-level{position:absolute;top:0;left:0;height:.6em;-moz-border-radius:.3em;-webkit-border-radius:.3em;border-radius:.3em;background:#fff;background:-moz-linear-gradient(top,#fff,#ccc);background:-webkit-gradient(linear,0% 0,0% 100%,from(#fff),to(#ccc));background:-webkit-linear-gradient(top,#fff,#ccc);background:-o-linear-gradient(top,#fff,#ccc);background:-ms-linear-gradient(top,#fff,#ccc);background:linear-gradient(top,#fff,#ccc)}.vjs-default-skin .vjs-volume-handle{position:absolute;top:-0.2em;width:.8em;height:.8em;background:#ccc;left:0;border:1px solid #fff;-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.vjs-default-skin div.vjs-progress-control{position:absolute;left:4.8em;right:4.8em;height:1.0em;width:auto;top:-1.3em;border-bottom:1px solid #1f1f1f;border-top:1px solid #222;background:#333;background:-moz-linear-gradient(top,#222,#333);background:-webkit-gradient(linear,0% 0,0% 100%,from(#222),to(#333));background:-webkit-linear-gradient(top,#222,#333);background:-o-linear-gradient(top,#333,#222);background:-ms-linear-gradient(top,#333,#222);background:linear-gradient(top,#333,#222)}.vjs-default-skin .vjs-progress-holder{position:relative;cursor:pointer!important;padding:0;margin:0;height:1.0em;-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em;background:#111;background:-moz-linear-gradient(top,#111,#262626);background:-webkit-gradient(linear,0% 0,0% 100%,from(#111),to(#262626));background:-webkit-linear-gradient(top,#111,#262626);background:-o-linear-gradient(top,#111,#262626);background:-ms-linear-gradient(top,#111,#262626);background:linear-gradient(top,#111,#262626)}.vjs-default-skin .vjs-progress-holder .vjs-play-progress,.vjs-default-skin .vjs-progress-holder .vjs-load-progress{position:absolute;display:block;height:1.0em;margin:0;padding:0;left:0;top:0;-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.vjs-default-skin .vjs-play-progress{background:#fff;background:-moz-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(0%,#fff),color-stop(50%,#d6d6d6),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:-o-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:-ms-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:#efefef;background:-moz-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(0%,#efefef),color-stop(50%,#f5f5f5),color-stop(50%,#dbdbdb),color-stop(100%,#f1f1f1));background:-webkit-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);background:-o-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);background:-ms-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#efefef',endColorstr='#f1f1f1',GradientType=0);background:linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%)}.vjs-default-skin .vjs-load-progress{opacity:.8;background:#666;background:-moz-linear-gradient(top,#666,#333);background:-webkit-gradient(linear,0% 0,0% 100%,from(#666),to(#333));background:-webkit-linear-gradient(top,#666,#333);background:-o-linear-gradient(top,#666,#333);background:-ms-linear-gradient(top,#666,#333);background:linear-gradient(top,#666,#333)}.vjs-default-skin div.vjs-seek-handle{position:absolute;width:16px;height:16px;margin-top:-0.3em;left:0;top:0;background:url('video-js.png') 0 -50px;-moz-border-radius:.8em;-webkit-border-radius:.8em;border-radius:.8em;-webkit-box-shadow:0 2px 4px 0 #000;-moz-box-shadow:0 2px 4px 0 #000;box-shadow:0 2px 4px 0 #000}.vjs-default-skin .vjs-time-controls{position:absolute;right:0;height:1.0em;width:4.8em;top:-1.3em;border-bottom:1px solid #1f1f1f;border-top:1px solid #222;background-color:#333;font-size:1em;line-height:1.0em;font-weight:normal;font-family:Helvetica,Arial,sans-serif;background:#333;background:-moz-linear-gradient(top,#222,#333);background:-webkit-gradient(linear,0% 0,0% 100%,from(#222),to(#333));background:-webkit-linear-gradient(top,#222,#333);background:-o-linear-gradient(top,#333,#222);background:-ms-linear-gradient(top,#333,#222);background:linear-gradient(top,#333,#222)}.vjs-default-skin .vjs-current-time{left:0}.vjs-default-skin .vjs-duration{right:0;display:none}.vjs-default-skin .vjs-remaining-time{right:0}.vjs-time-divider{display:none}.vjs-default-skin .vjs-time-control{font-size:1em;line-height:1;font-weight:normal;font-family:Helvetica,Arial,sans-serif}.vjs-default-skin .vjs-time-control span{line-height:25px}.vjs-secondary-controls{float:right}.vjs-default-skin .vjs-fullscreen-control{width:3.8em;cursor:pointer!important;float:right}.vjs-default-skin .vjs-fullscreen-control div{width:16px;height:16px;background:url('video-js.png') -50px 0;margin:.5em auto 0}.vjs-default-skin.vjs-fullscreen .vjs-fullscreen-control div{background:url('video-js.png') -75px 0}.vjs-default-skin .vjs-big-play-button{display:block;z-index:2;position:absolute;top:50%;left:50%;width:8.0em;height:8.0em;margin:-42px 0 0 -42px;text-align:center;vertical-align:center;cursor:pointer!important;border:.2em solid #fff;opacity:.95;-webkit-border-radius:25px;-moz-border-radius:25px;border-radius:25px;background:#454545;background:-moz-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(0%,#454545),color-stop(50%,#232323),color-stop(50%,#161616),color-stop(100%,#3f3f3f));background:-webkit-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);background:-o-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);background:-ms-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#454545',endColorstr='#3f3f3f',GradientType=0);background:linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);-webkit-box-shadow:4px 4px 8px #000;-moz-box-shadow:4px 4px 8px #000;box-shadow:4px 4px 8px #000}.vjs-default-skin div.vjs-big-play-button:hover{-webkit-box-shadow:0 0 80px #fff;-moz-box-shadow:0 0 80px #fff;box-shadow:0 0 80px #fff}.vjs-default-skin div.vjs-big-play-button span{position:absolute;top:50%;left:50%;display:block;width:35px;height:42px;margin:-20px 0 0 -15px;background:url('video-js.png') -100px 0}.vjs-loading-spinner{display:none;position:absolute;top:50%;left:50%;width:55px;height:55px;margin:-28px 0 0 -28px;-webkit-animation-name:rotatethis;-webkit-animation-duration:1s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:rotatethis;-moz-animation-duration:1s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear}@-webkit-keyframes rotatethis{0%{-webkit-transform:scale(0.6) rotate(0deg)}12.5%{-webkit-transform:scale(0.6) rotate(0deg)}12.51%{-webkit-transform:scale(0.6) rotate(45deg)}25%{-webkit-transform:scale(0.6) rotate(45deg)}25.01%{-webkit-transform:scale(0.6) rotate(90deg)}37.5%{-webkit-transform:scale(0.6) rotate(90deg)}37.51%{-webkit-transform:scale(0.6) rotate(135deg)}50%{-webkit-transform:scale(0.6) rotate(135deg)}50.01%{-webkit-transform:scale(0.6) rotate(180deg)}62.5%{-webkit-transform:scale(0.6) rotate(180deg)}62.51%{-webkit-transform:scale(0.6) rotate(225deg)}75%{-webkit-transform:scale(0.6) rotate(225deg)}75.01%{-webkit-transform:scale(0.6) rotate(270deg)}87.5%{-webkit-transform:scale(0.6) rotate(270deg)}87.51%{-webkit-transform:scale(0.6) rotate(315deg)}100%{-webkit-transform:scale(0.6) rotate(315deg)}}@-moz-keyframes rotatethis{0%{-moz-transform:scale(0.6) rotate(0deg)}12.5%{-moz-transform:scale(0.6) rotate(0deg)}12.51%{-moz-transform:scale(0.6) rotate(45deg)}25%{-moz-transform:scale(0.6) rotate(45deg)}25.01%{-moz-transform:scale(0.6) rotate(90deg)}37.5%{-moz-transform:scale(0.6) rotate(90deg)}37.51%{-moz-transform:scale(0.6) rotate(135deg)}50%{-moz-transform:scale(0.6) rotate(135deg)}50.01%{-moz-transform:scale(0.6) rotate(180deg)}62.5%{-moz-transform:scale(0.6) rotate(180deg)}62.51%{-moz-transform:scale(0.6) rotate(225deg)}75%{-moz-transform:scale(0.6) rotate(225deg)}75.01%{-moz-transform:scale(0.6) rotate(270deg)}87.5%{-moz-transform:scale(0.6) rotate(270deg)}87.51%{-moz-transform:scale(0.6) rotate(315deg)}100%{-moz-transform:scale(0.6) rotate(315deg)}}div.vjs-loading-spinner .ball1{opacity:.12;position:absolute;left:20px;top:0;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball2{opacity:.25;position:absolute;left:34px;top:6px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball3{opacity:.37;position:absolute;left:40px;top:20px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball4{opacity:.50;position:absolute;left:34px;top:34px;width:13px;height:13px;background:#fff;border-radius:10px;-webkit-border-radius:10px;-moz-border-radius:15px;border:1px solid #ccc}div.vjs-loading-spinner .ball5{opacity:.62;position:absolute;left:20px;top:40px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball6{opacity:.75;position:absolute;left:6px;top:34px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball7{opacity:.87;position:absolute;left:0;top:20px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball8{opacity:1.00;position:absolute;left:6px;top:6px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}.vjs-default-skin .vjs-menu-button{float:right;margin:.2em .5em 0 0;padding:0;width:3em;height:2em;cursor:pointer!important;border:1px solid #111;-moz-border-radius:.3em;-webkit-border-radius:.3em;border-radius:.3em;background:#4d4d4d;background:-moz-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#4d4d4d),color-stop(50%,#3f3f3f),color-stop(50%,#333),color-stop(100%,#252525));background:-webkit-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-o-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-ms-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%)}.vjs-default-skin .vjs-menu-button div{background:url('video-js.png') 0 -75px no-repeat;width:16px;height:16px;margin:.2em auto 0;padding:0}.vjs-default-skin .vjs-menu-button ul{display:none;opacity:.8;padding:0;margin:0;position:absolute;width:10em;bottom:2em;max-height:15em;left:-3.5em;background-color:#111;border:2px solid #333;-moz-border-radius:.7em;-webkit-border-radius:1em;border-radius:.5em;-webkit-box-shadow:0 2px 4px 0 #000;-moz-box-shadow:0 2px 4px 0 #000;box-shadow:0 2px 4px 0 #000;overflow:auto}.vjs-default-skin .vjs-menu-button:focus ul,.vjs-default-skin .vjs-menu-button:hover ul{display:block;list-style:none}.vjs-default-skin .vjs-menu-button ul li{list-style:none;margin:0;padding:.3em 0 .3em 20px;line-height:1.4em;font-size:1.2em;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;text-align:left}.vjs-default-skin .vjs-menu-button ul li.vjs-selected{text-decoration:underline;background:url('video-js.png') -125px -50px no-repeat}.vjs-default-skin .vjs-menu-button ul li:focus,.vjs-default-skin .vjs-menu-button ul li:hover,.vjs-default-skin .vjs-menu-button ul li.vjs-selected:focus,.vjs-default-skin .vjs-menu-button ul li.vjs-selected:hover{background-color:#ccc;color:#111;outline:0}.vjs-default-skin .vjs-menu-button ul li.vjs-menu-title{text-align:center;text-transform:uppercase;font-size:1em;line-height:2em;padding:0;margin:0 0 .3em 0;color:#fff;font-weight:bold;cursor:default;background:#4d4d4d;background:-moz-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#4d4d4d),color-stop(50%,#3f3f3f),color-stop(50%,#333),color-stop(100%,#252525));background:-webkit-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-o-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-ms-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%)}.vjs-default-skin .vjs-captions-button div{background-position:-25px -75px}.vjs-default-skin .vjs-chapters-button div{background-position:-100px -75px}.vjs-default-skin .vjs-chapters-button ul{width:20em;left:-8.5em}
\ No newline at end of file +/*! +Video.js Default Styles (http://videojs.com) +Version 4.2.1 +Create your own skin at http://designer.videojs.com +*/.vjs-default-skin{color:#ccc}@font-face{font-family:VideoJS;src:url(font/vjs.eot);src:url(font/vjs.eot?#iefix) format('embedded-opentype'),url(font/vjs.woff) format('woff'),url(font/vjs.ttf) format('truetype');font-weight:400;font-style:normal}.vjs-default-skin .vjs-slider{outline:0;position:relative;cursor:pointer;padding:0;background-color:#333;background-color:rgba(51,51,51,.9)}.vjs-default-skin .vjs-slider:focus{-webkit-box-shadow:0 0 2em #fff;-moz-box-shadow:0 0 2em #fff;box-shadow:0 0 2em #fff}.vjs-default-skin .vjs-slider-handle{position:absolute;left:0;top:0}.vjs-default-skin .vjs-slider-handle:before{content:"\e009";font-family:VideoJS;font-size:1em;line-height:1;text-align:center;text-shadow:0 0 1em #fff;position:absolute;top:0;left:0;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.vjs-default-skin .vjs-control-bar{display:none;position:absolute;bottom:0;left:0;right:0;height:3em;background-color:#07141e;background-color:rgba(7,20,30,.7)}.vjs-default-skin.vjs-has-started .vjs-control-bar{display:block;visibility:visible;opacity:1;-webkit-transition:visibility .1s,opacity .1s;-moz-transition:visibility .1s,opacity .1s;-o-transition:visibility .1s,opacity .1s;transition:visibility .1s,opacity .1s}.vjs-default-skin.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar{display:block;visibility:hidden;opacity:0;-webkit-transition:visibility 1s,opacity 1s;-moz-transition:visibility 1s,opacity 1s;-o-transition:visibility 1s,opacity 1s;transition:visibility 1s,opacity 1s}.vjs-default-skin.vjs-controls-disabled .vjs-control-bar{display:none}.vjs-default-skin.vjs-using-native-controls .vjs-control-bar{display:none}@media \0screen{.vjs-default-skin.vjs-user-inactive.vjs-playing .vjs-control-bar :before{content:""}}.vjs-default-skin .vjs-control{outline:0;position:relative;float:left;text-align:center;margin:0;padding:0;height:3em;width:4em}.vjs-default-skin .vjs-control:before{font-family:VideoJS;font-size:1.5em;line-height:2;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center;text-shadow:1px 1px 1px rgba(0,0,0,.5)}.vjs-default-skin .vjs-control:focus:before,.vjs-default-skin .vjs-control:hover:before{text-shadow:0 0 1em #fff}.vjs-default-skin .vjs-control:focus{}.vjs-default-skin .vjs-control-text{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.vjs-default-skin .vjs-play-control{width:5em;cursor:pointer}.vjs-default-skin .vjs-play-control:before{content:"\e001"}.vjs-default-skin.vjs-playing .vjs-play-control:before{content:"\e002"}.vjs-default-skin .vjs-mute-control,.vjs-default-skin .vjs-volume-menu-button{cursor:pointer;float:right}.vjs-default-skin .vjs-mute-control:before,.vjs-default-skin .vjs-volume-menu-button:before{content:"\e006"}.vjs-default-skin .vjs-mute-control.vjs-vol-0:before,.vjs-default-skin .vjs-volume-menu-button.vjs-vol-0:before{content:"\e003"}.vjs-default-skin .vjs-mute-control.vjs-vol-1:before,.vjs-default-skin .vjs-volume-menu-button.vjs-vol-1:before{content:"\e004"}.vjs-default-skin .vjs-mute-control.vjs-vol-2:before,.vjs-default-skin .vjs-volume-menu-button.vjs-vol-2:before{content:"\e005"}.vjs-default-skin .vjs-volume-control{width:5em;float:right}.vjs-default-skin .vjs-volume-bar{width:5em;height:.6em;margin:1.1em auto 0}.vjs-default-skin .vjs-volume-menu-button .vjs-menu-content{height:2.9em}.vjs-default-skin .vjs-volume-level{position:absolute;top:0;left:0;height:.5em;background:#66a8cc url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAP0lEQVQIHWWMAQoAIAgDR/QJ/Ub//04+w7ZICBwcOg5FZi5iBB82AGzixEglJrd4TVK5XUJpskSTEvpdFzX9AB2pGziSQcvAAAAAAElFTkSuQmCC) -50% 0 repeat}.vjs-default-skin .vjs-volume-bar .vjs-volume-handle{width:.5em;height:.5em}.vjs-default-skin .vjs-volume-handle:before{font-size:.9em;top:-.2em;left:-.2em;width:1em;height:1em}.vjs-default-skin .vjs-volume-menu-button .vjs-menu .vjs-menu-content{width:6em;left:-4em}.vjs-default-skin .vjs-progress-control{position:absolute;left:0;right:0;width:auto;font-size:.3em;height:1em;top:-1em;-webkit-transition:all .4s;-moz-transition:all .4s;-o-transition:all .4s;transition:all .4s}.vjs-default-skin:hover .vjs-progress-control{font-size:.9em;-webkit-transition:all .2s;-moz-transition:all .2s;-o-transition:all .2s;transition:all .2s}.vjs-default-skin .vjs-progress-holder{height:100%}.vjs-default-skin .vjs-progress-holder .vjs-play-progress,.vjs-default-skin .vjs-progress-holder .vjs-load-progress{position:absolute;display:block;height:100%;margin:0;padding:0;left:0;top:0}.vjs-default-skin .vjs-play-progress{background:#66a8cc url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAP0lEQVQIHWWMAQoAIAgDR/QJ/Ub//04+w7ZICBwcOg5FZi5iBB82AGzixEglJrd4TVK5XUJpskSTEvpdFzX9AB2pGziSQcvAAAAAAElFTkSuQmCC) -50% 0 repeat}.vjs-default-skin .vjs-load-progress{background:#646464;background:rgba(255,255,255,.4)}.vjs-default-skin .vjs-seek-handle{width:1.5em;height:100%}.vjs-default-skin .vjs-seek-handle:before{padding-top:.1em}.vjs-default-skin .vjs-time-controls{font-size:1em;line-height:3em}.vjs-default-skin .vjs-current-time{float:left}.vjs-default-skin .vjs-duration{float:left}.vjs-default-skin .vjs-remaining-time{display:none;float:left}.vjs-time-divider{float:left;line-height:3em}.vjs-default-skin .vjs-fullscreen-control{width:3.8em;cursor:pointer;float:right}.vjs-default-skin .vjs-fullscreen-control:before{content:"\e000"}.vjs-default-skin.vjs-fullscreen .vjs-fullscreen-control:before{content:"\e00b"}.vjs-default-skin .vjs-big-play-button{left:.5em;top:.5em;font-size:3em;display:block;z-index:2;position:absolute;width:4em;height:2.6em;text-align:center;vertical-align:middle;cursor:pointer;opacity:1;background-color:#07141e;background-color:rgba(7,20,30,.7);border:.1em solid #3b4249;-webkit-border-radius:.8em;-moz-border-radius:.8em;border-radius:.8em;-webkit-box-shadow:0 0 1em rgba(255,255,255,.25);-moz-box-shadow:0 0 1em rgba(255,255,255,.25);box-shadow:0 0 1em rgba(255,255,255,.25);-webkit-transition:all .4s;-moz-transition:all .4s;-o-transition:all .4s;transition:all .4s}.vjs-default-skin.vjs-controls-disabled .vjs-big-play-button{display:none}.vjs-default-skin.vjs-has-started .vjs-big-play-button{display:none}.vjs-default-skin.vjs-using-native-controls .vjs-big-play-button{display:none}.vjs-default-skin:hover .vjs-big-play-button,.vjs-default-skin .vjs-big-play-button:focus{outline:0;border-color:#fff;background-color:#505050;background-color:rgba(50,50,50,.75);-webkit-box-shadow:0 0 3em #fff;-moz-box-shadow:0 0 3em #fff;box-shadow:0 0 3em #fff;-webkit-transition:all 0s;-moz-transition:all 0s;-o-transition:all 0s;transition:all 0s}.vjs-default-skin .vjs-big-play-button:before{content:"\e001";font-family:VideoJS;line-height:2.6em;text-shadow:.05em .05em .1em #000;text-align:center;position:absolute;left:0;width:100%;height:100%}.vjs-loading-spinner{display:none;position:absolute;top:50%;left:50%;font-size:5em;line-height:1;width:1em;height:1em;margin-left:-.5em;margin-top:-.5em;opacity:.75;-webkit-animation:spin 1.5s infinite linear;-moz-animation:spin 1.5s infinite linear;-o-animation:spin 1.5s infinite linear;animation:spin 1.5s infinite linear}.vjs-default-skin .vjs-loading-spinner:before{content:"\e00a";font-family:VideoJS;position:absolute;top:0;left:0;width:1em;height:1em;text-align:center;text-shadow:0 0 .1em #000}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.vjs-default-skin .vjs-menu-button{float:right;cursor:pointer}.vjs-default-skin .vjs-menu{display:none;position:absolute;bottom:0;left:0;width:0;height:0;margin-bottom:3em;border-left:2em solid transparent;border-right:2em solid transparent;border-top:1.55em solid #000;border-top-color:rgba(7,40,50,.5)}.vjs-default-skin .vjs-menu-button .vjs-menu .vjs-menu-content{display:block;padding:0;margin:0;position:absolute;width:10em;bottom:1.5em;max-height:15em;overflow:auto;left:-5em;background-color:#07141e;background-color:rgba(7,20,30,.7);-webkit-box-shadow:-.2em -.2em .3em rgba(255,255,255,.2);-moz-box-shadow:-.2em -.2em .3em rgba(255,255,255,.2);box-shadow:-.2em -.2em .3em rgba(255,255,255,.2)}.vjs-default-skin .vjs-menu-button:hover .vjs-menu{display:block}.vjs-default-skin .vjs-menu-button ul li{list-style:none;margin:0;padding:.3em 0;line-height:1.4em;font-size:1.2em;text-align:center;text-transform:lowercase}.vjs-default-skin .vjs-menu-button ul li.vjs-selected{background-color:#000}.vjs-default-skin .vjs-menu-button ul li:focus,.vjs-default-skin .vjs-menu-button ul li:hover,.vjs-default-skin .vjs-menu-button ul li.vjs-selected:focus,.vjs-default-skin .vjs-menu-button ul li.vjs-selected:hover{outline:0;color:#111;background-color:#fff;background-color:rgba(255,255,255,.75);-webkit-box-shadow:0 0 1em #fff;-moz-box-shadow:0 0 1em #fff;box-shadow:0 0 1em #fff}.vjs-default-skin .vjs-menu-button ul li.vjs-menu-title{text-align:center;text-transform:uppercase;font-size:1em;line-height:2em;padding:0;margin:0 0 .3em;font-weight:700;cursor:default}.vjs-default-skin .vjs-subtitles-button:before{content:"\e00c"}.vjs-default-skin .vjs-captions-button:before{content:"\e008"}.vjs-default-skin .vjs-captions-button:focus .vjs-control-content:before,.vjs-default-skin .vjs-captions-button:hover .vjs-control-content:before{-webkit-box-shadow:0 0 1em #fff;-moz-box-shadow:0 0 1em #fff;box-shadow:0 0 1em #fff}.video-js{background-color:#000;position:relative;padding:0;font-size:10px;vertical-align:middle;font-weight:400;font-style:normal;font-family:Arial,sans-serif;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.video-js .vjs-tech{position:absolute;top:0;left:0;width:100%;height:100%}.video-js:-moz-full-screen{position:absolute}body.vjs-full-window{padding:0;margin:0;height:100%;overflow-y:auto}.video-js.vjs-fullscreen{position:fixed;overflow:hidden;z-index:1000;left:0;top:0;bottom:0;right:0;width:100%!important;height:100%!important;_position:absolute}.video-js:-webkit-full-screen{width:100%!important;height:100%!important}.video-js.vjs-fullscreen.vjs-user-inactive{cursor:none}.vjs-poster{background-repeat:no-repeat;background-position:50% 50%;background-size:contain;cursor:pointer;height:100%;margin:0;padding:0;position:relative;width:100%}.vjs-poster img{display:block;margin:0 auto;max-height:100%;padding:0;width:100%}.video-js.vjs-using-native-controls .vjs-poster{display:none}.video-js .vjs-text-track-display{text-align:center;position:absolute;bottom:4em;left:1em;right:1em}.video-js .vjs-text-track{display:none;font-size:1.4em;text-align:center;margin-bottom:.1em;background-color:#000;background-color:rgba(0,0,0,.5)}.video-js .vjs-subtitles{color:#fff}.video-js .vjs-captions{color:#fc6}.vjs-tt-cue{display:block}.vjs-default-skin .vjs-hidden{display:none}.vjs-lock-showing{display:block!important;opacity:1;visibility:visible}
\ No newline at end of file diff --git a/extlib/video-js/video-js.png b/extlib/video-js/video-js.png Binary files differdeleted file mode 100644 index 100bc7f8..00000000 --- a/extlib/video-js/video-js.png +++ /dev/null diff --git a/extlib/video-js/video-js.swf b/extlib/video-js/video-js.swf Binary files differnew file mode 100644 index 00000000..d15fbc3f --- /dev/null +++ b/extlib/video-js/video-js.swf diff --git a/extlib/video-js/video.dev.js b/extlib/video-js/video.dev.js new file mode 100644 index 00000000..2ff69a8c --- /dev/null +++ b/extlib/video-js/video.dev.js @@ -0,0 +1,6457 @@ +/** + * @fileoverview Main function src. + */ + +// HTML5 Shiv. Must be in <head> to support older browsers. +document.createElement('video'); +document.createElement('audio'); +document.createElement('track'); + +/** + * Doubles as the main function for users to create a player instance and also + * the main library object. + * + * @param {String|Element} id Video element or video element ID + * @param {Object=} options Optional options object for config/settings + * @param {Function=} ready Optional ready callback + * @return {vjs.Player} A player instance + */ +var vjs = function(id, options, ready){ + var tag; // Element of ID + + // Allow for element or ID to be passed in + // String ID + if (typeof id === 'string') { + + // Adjust for jQuery ID syntax + if (id.indexOf('#') === 0) { + id = id.slice(1); + } + + // If a player instance has already been created for this ID return it. + if (vjs.players[id]) { + return vjs.players[id]; + + // Otherwise get element for ID + } else { + tag = vjs.el(id); + } + + // ID is a media element + } else { + tag = id; + } + + // Check for a useable element + if (!tag || !tag.nodeName) { // re: nodeName, could be a box div also + throw new TypeError('The element or ID supplied is not valid. (videojs)'); // Returns + } + + // Element may have a player attr referring to an already created player instance. + // If not, set up a new player and return the instance. + return tag['player'] || new vjs.Player(tag, options, ready); +}; + +// Extended name, also available externally, window.videojs +var videojs = vjs; +window.videojs = window.vjs = vjs; + +// CDN Version. Used to target right flash swf. +vjs.CDN_VERSION = '4.2'; +vjs.ACCESS_PROTOCOL = ('https:' == document.location.protocol ? 'https://' : 'http://'); + +/** + * Global Player instance options, surfaced from vjs.Player.prototype.options_ + * vjs.options = vjs.Player.prototype.options_ + * All options should use string keys so they avoid + * renaming by closure compiler + * @type {Object} + */ +vjs.options = { + // Default order of fallback technology + 'techOrder': ['html5','flash'], + // techOrder: ['flash','html5'], + + 'html5': {}, + 'flash': {}, + + // Default of web browser is 300x150. Should rely on source width/height. + 'width': 300, + 'height': 150, + // defaultVolume: 0.85, + 'defaultVolume': 0.00, // The freakin seaguls are driving me crazy! + + // Included control sets + 'children': { + 'mediaLoader': {}, + 'posterImage': {}, + 'textTrackDisplay': {}, + 'loadingSpinner': {}, + 'bigPlayButton': {}, + 'controlBar': {} + }, + + // Default message to show when a video cannot be played. + 'notSupportedMessage': 'Sorry, no compatible source and playback ' + + 'technology were found for this video. Try using another browser ' + + 'like <a href="http://bit.ly/ccMUEC">Chrome</a> or download the ' + + 'latest <a href="http://adobe.ly/mwfN1">Adobe Flash Player</a>.' +}; + +// Set CDN Version of swf +// The added (+) blocks the replace from changing this 4.2 string +if (vjs.CDN_VERSION !== 'GENERATED'+'_CDN_VSN') { + videojs.options['flash']['swf'] = vjs.ACCESS_PROTOCOL + 'vjs.zencdn.net/'+vjs.CDN_VERSION+'/video-js.swf'; +} + +/** + * Global player list + * @type {Object} + */ +vjs.players = {}; +/** + * Core Object/Class for objects that use inheritance + contstructors + * @constructor + */ +vjs.CoreObject = vjs['CoreObject'] = function(){}; +// Manually exporting vjs['CoreObject'] here for Closure Compiler +// because of the use of the extend/create class methods +// If we didn't do this, those functions would get flattend to something like +// `a = ...` and `this.prototype` would refer to the global object instead of +// CoreObject + +/** + * Create a new object that inherits from this Object + * @param {Object} props Functions and properties to be applied to the + * new object's prototype + * @return {vjs.CoreObject} Returns an object that inherits from CoreObject + * @this {*} + */ +vjs.CoreObject.extend = function(props){ + var init, subObj; + + props = props || {}; + // Set up the constructor using the supplied init method + // or using the init of the parent object + // Make sure to check the unobfuscated version for external libs + init = props['init'] || props.init || this.prototype['init'] || this.prototype.init || function(){}; + // In Resig's simple class inheritance (previously used) the constructor + // is a function that calls `this.init.apply(arguments)` + // However that would prevent us from using `ParentObject.call(this);` + // in a Child constuctor because the `this` in `this.init` + // would still refer to the Child and cause an inifinite loop. + // We would instead have to do + // `ParentObject.prototype.init.apply(this, argumnents);` + // Bleh. We're not creating a _super() function, so it's good to keep + // the parent constructor reference simple. + subObj = function(){ + init.apply(this, arguments); + }; + + // Inherit from this object's prototype + subObj.prototype = vjs.obj.create(this.prototype); + // Reset the constructor property for subObj otherwise + // instances of subObj would have the constructor of the parent Object + subObj.prototype.constructor = subObj; + + // Make the class extendable + subObj.extend = vjs.CoreObject.extend; + // Make a function for creating instances + subObj.create = vjs.CoreObject.create; + + // Extend subObj's prototype with functions and other properties from props + for (var name in props) { + if (props.hasOwnProperty(name)) { + subObj.prototype[name] = props[name]; + } + } + + return subObj; +}; + +/** + * Create a new instace of this Object class + * @return {vjs.CoreObject} Returns an instance of a CoreObject subclass + * @this {*} + */ +vjs.CoreObject.create = function(){ + // Create a new object that inherits from this object's prototype + var inst = vjs.obj.create(this.prototype); + + // Apply this constructor function to the new object + this.apply(inst, arguments); + + // Return the new object + return inst; +}; +/** + * @fileoverview Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/) + * (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible) + * This should work very similarly to jQuery's events, however it's based off the book version which isn't as + * robust as jquery's, so there's probably some differences. + */ + +/** + * Add an event listener to element + * It stores the handler function in a separate cache object + * and adds a generic handler to the element's event, + * along with a unique id (guid) to the element. + * @param {Element|Object} elem Element or object to bind listeners to + * @param {String} type Type of event to bind to. + * @param {Function} fn Event listener. + */ +vjs.on = function(elem, type, fn){ + var data = vjs.getData(elem); + + // We need a place to store all our handler data + if (!data.handlers) data.handlers = {}; + + if (!data.handlers[type]) data.handlers[type] = []; + + if (!fn.guid) fn.guid = vjs.guid++; + + data.handlers[type].push(fn); + + if (!data.dispatcher) { + data.disabled = false; + + data.dispatcher = function (event){ + + if (data.disabled) return; + event = vjs.fixEvent(event); + + var handlers = data.handlers[event.type]; + + if (handlers) { + // Copy handlers so if handlers are added/removed during the process it doesn't throw everything off. + var handlersCopy = handlers.slice(0); + + for (var m = 0, n = handlersCopy.length; m < n; m++) { + if (event.isImmediatePropagationStopped()) { + break; + } else { + handlersCopy[m].call(elem, event); + } + } + } + }; + } + + if (data.handlers[type].length == 1) { + if (document.addEventListener) { + elem.addEventListener(type, data.dispatcher, false); + } else if (document.attachEvent) { + elem.attachEvent('on' + type, data.dispatcher); + } + } +}; + +/** + * Removes event listeners from an element + * @param {Element|Object} elem Object to remove listeners from + * @param {String=} type Type of listener to remove. Don't include to remove all events from element. + * @param {Function} fn Specific listener to remove. Don't incldue to remove listeners for an event type. + */ +vjs.off = function(elem, type, fn) { + // Don't want to add a cache object through getData if not needed + if (!vjs.hasData(elem)) return; + + var data = vjs.getData(elem); + + // If no events exist, nothing to unbind + if (!data.handlers) { return; } + + // Utility function + var removeType = function(t){ + data.handlers[t] = []; + vjs.cleanUpEvents(elem,t); + }; + + // Are we removing all bound events? + if (!type) { + for (var t in data.handlers) removeType(t); + return; + } + + var handlers = data.handlers[type]; + + // If no handlers exist, nothing to unbind + if (!handlers) return; + + // If no listener was provided, remove all listeners for type + if (!fn) { + removeType(type); + return; + } + + // We're only removing a single handler + if (fn.guid) { + for (var n = 0; n < handlers.length; n++) { + if (handlers[n].guid === fn.guid) { + handlers.splice(n--, 1); + } + } + } + + vjs.cleanUpEvents(elem, type); +}; + +/** + * Clean up the listener cache and dispatchers + * @param {Element|Object} elem Element to clean up + * @param {String} type Type of event to clean up + */ +vjs.cleanUpEvents = function(elem, type) { + var data = vjs.getData(elem); + + // Remove the events of a particular type if there are none left + if (data.handlers[type].length === 0) { + delete data.handlers[type]; + // data.handlers[type] = null; + // Setting to null was causing an error with data.handlers + + // Remove the meta-handler from the element + if (document.removeEventListener) { + elem.removeEventListener(type, data.dispatcher, false); + } else if (document.detachEvent) { + elem.detachEvent('on' + type, data.dispatcher); + } + } + + // Remove the events object if there are no types left + if (vjs.isEmpty(data.handlers)) { + delete data.handlers; + delete data.dispatcher; + delete data.disabled; + + // data.handlers = null; + // data.dispatcher = null; + // data.disabled = null; + } + + // Finally remove the expando if there is no data left + if (vjs.isEmpty(data)) { + vjs.removeData(elem); + } +}; + +/** + * Fix a native event to have standard property values + * @param {Object} event Event object to fix + * @return {Object} + */ +vjs.fixEvent = function(event) { + + function returnTrue() { return true; } + function returnFalse() { return false; } + + // Test if fixing up is needed + // Used to check if !event.stopPropagation instead of isPropagationStopped + // But native events return true for stopPropagation, but don't have + // other expected methods like isPropagationStopped. Seems to be a problem + // with the Javascript Ninja code. So we're just overriding all events now. + if (!event || !event.isPropagationStopped) { + var old = event || window.event; + + event = {}; + // Clone the old object so that we can modify the values event = {}; + // IE8 Doesn't like when you mess with native event properties + // Firefox returns false for event.hasOwnProperty('type') and other props + // which makes copying more difficult. + // TODO: Probably best to create a whitelist of event props + for (var key in old) { + // Safari 6.0.3 warns you if you try to copy deprecated layerX/Y + if (key !== 'layerX' && key !== 'layerY') { + event[key] = old[key]; + } + } + + // The event occurred on this element + if (!event.target) { + event.target = event.srcElement || document; + } + + // Handle which other element the event is related to + event.relatedTarget = event.fromElement === event.target ? + event.toElement : + event.fromElement; + + // Stop the default browser action + event.preventDefault = function () { + if (old.preventDefault) { + old.preventDefault(); + } + event.returnValue = false; + event.isDefaultPrevented = returnTrue; + }; + + event.isDefaultPrevented = returnFalse; + + // Stop the event from bubbling + event.stopPropagation = function () { + if (old.stopPropagation) { + old.stopPropagation(); + } + event.cancelBubble = true; + event.isPropagationStopped = returnTrue; + }; + + event.isPropagationStopped = returnFalse; + + // Stop the event from bubbling and executing other handlers + event.stopImmediatePropagation = function () { + if (old.stopImmediatePropagation) { + old.stopImmediatePropagation(); + } + event.isImmediatePropagationStopped = returnTrue; + event.stopPropagation(); + }; + + event.isImmediatePropagationStopped = returnFalse; + + // Handle mouse position + if (event.clientX != null) { + var doc = document.documentElement, body = document.body; + + event.pageX = event.clientX + + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - + (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + + (doc && doc.scrollTop || body && body.scrollTop || 0) - + (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Handle key presses + event.which = event.charCode || event.keyCode; + + // Fix button for mouse clicks: + // 0 == left; 1 == middle; 2 == right + if (event.button != null) { + event.button = (event.button & 1 ? 0 : + (event.button & 4 ? 1 : + (event.button & 2 ? 2 : 0))); + } + } + + // Returns fixed-up instance + return event; +}; + +/** + * Trigger an event for an element + * @param {Element|Object} elem Element to trigger an event on + * @param {String} event Type of event to trigger + */ +vjs.trigger = function(elem, event) { + // Fetches element data and a reference to the parent (for bubbling). + // Don't want to add a data object to cache for every parent, + // so checking hasData first. + var elemData = (vjs.hasData(elem)) ? vjs.getData(elem) : {}; + var parent = elem.parentNode || elem.ownerDocument; + // type = event.type || event, + // handler; + + // If an event name was passed as a string, creates an event out of it + if (typeof event === 'string') { + event = { type:event, target:elem }; + } + // Normalizes the event properties. + event = vjs.fixEvent(event); + + // If the passed element has a dispatcher, executes the established handlers. + if (elemData.dispatcher) { + elemData.dispatcher.call(elem, event); + } + + // Unless explicitly stopped or the event does not bubble (e.g. media events) + // recursively calls this function to bubble the event up the DOM. + if (parent && !event.isPropagationStopped() && event.bubbles !== false) { + vjs.trigger(parent, event); + + // If at the top of the DOM, triggers the default action unless disabled. + } else if (!parent && !event.isDefaultPrevented()) { + var targetData = vjs.getData(event.target); + + // Checks if the target has a default action for this event. + if (event.target[event.type]) { + // Temporarily disables event dispatching on the target as we have already executed the handler. + targetData.disabled = true; + // Executes the default action. + if (typeof event.target[event.type] === 'function') { + event.target[event.type](); + } + // Re-enables event dispatching. + targetData.disabled = false; + } + } + + // Inform the triggerer if the default was prevented by returning false + return !event.isDefaultPrevented(); + /* Original version of js ninja events wasn't complete. + * We've since updated to the latest version, but keeping this around + * for now just in case. + */ + // // Added in attion to book. Book code was broke. + // event = typeof event === 'object' ? + // event[vjs.expando] ? + // event : + // new vjs.Event(type, event) : + // new vjs.Event(type); + + // event.type = type; + // if (handler) { + // handler.call(elem, event); + // } + + // // Clean up the event in case it is being reused + // event.result = undefined; + // event.target = elem; +}; + +/** + * Trigger a listener only once for an event + * @param {Element|Object} elem Element or object to + * @param {[type]} type [description] + * @param {Function} fn [description] + * @return {[type]} + */ +vjs.one = function(elem, type, fn) { + var func = function(){ + vjs.off(elem, type, func); + fn.apply(this, arguments); + }; + func.guid = fn.guid = fn.guid || vjs.guid++; + vjs.on(elem, type, func); +}; +var hasOwnProp = Object.prototype.hasOwnProperty; + +/** + * Creates an element and applies properties. + * @param {String=} tagName Name of tag to be created. + * @param {Object=} properties Element properties to be applied. + * @return {Element} + */ +vjs.createEl = function(tagName, properties){ + var el, propName; + + el = document.createElement(tagName || 'div'); + + for (propName in properties){ + if (hasOwnProp.call(properties, propName)) { + //el[propName] = properties[propName]; + // Not remembering why we were checking for dash + // but using setAttribute means you have to use getAttribute + + // The check for dash checks for the aria-* attributes, like aria-label, aria-valuemin. + // The additional check for "role" is because the default method for adding attributes does not + // add the attribute "role". My guess is because it's not a valid attribute in some namespaces, although + // browsers handle the attribute just fine. The W3C allows for aria-* attributes to be used in pre-HTML5 docs. + // http://www.w3.org/TR/wai-aria-primer/#ariahtml. Using setAttribute gets around this problem. + + if (propName.indexOf('aria-') !== -1 || propName=='role') { + el.setAttribute(propName, properties[propName]); + } else { + el[propName] = properties[propName]; + } + } + } + return el; +}; + +/** + * Uppercase the first letter of a string + * @param {String} string String to be uppercased + * @return {String} + */ +vjs.capitalize = function(string){ + return string.charAt(0).toUpperCase() + string.slice(1); +}; + +/** + * Object functions container + * @type {Object} + */ +vjs.obj = {}; + +/** + * Object.create shim for prototypal inheritance. + * https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create + * @param {Object} obj Object to use as prototype + */ + vjs.obj.create = Object.create || function(obj){ + //Create a new function called 'F' which is just an empty object. + function F() {} + + //the prototype of the 'F' function should point to the + //parameter of the anonymous function. + F.prototype = obj; + + //create a new constructor function based off of the 'F' function. + return new F(); +}; + +/** + * Loop through each property in an object and call a function + * whose arguments are (key,value) + * @param {Object} obj Object of properties + * @param {Function} fn Function to be called on each property. + * @this {*} + */ +vjs.obj.each = function(obj, fn, context){ + for (var key in obj) { + if (hasOwnProp.call(obj, key)) { + fn.call(context || this, key, obj[key]); + } + } +}; + +/** + * Merge two objects together and return the original. + * @param {Object} obj1 + * @param {Object} obj2 + * @return {Object} + */ +vjs.obj.merge = function(obj1, obj2){ + if (!obj2) { return obj1; } + for (var key in obj2){ + if (hasOwnProp.call(obj2, key)) { + obj1[key] = obj2[key]; + } + } + return obj1; +}; + +/** + * Merge two objects, and merge any properties that are objects + * instead of just overwriting one. Uses to merge options hashes + * where deeper default settings are important. + * @param {Object} obj1 Object to override + * @param {Object} obj2 Overriding object + * @return {Object} New object. Obj1 and Obj2 will be untouched. + */ +vjs.obj.deepMerge = function(obj1, obj2){ + var key, val1, val2; + + // make a copy of obj1 so we're not ovewriting original values. + // like prototype.options_ and all sub options objects + obj1 = vjs.obj.copy(obj1); + + for (key in obj2){ + if (hasOwnProp.call(obj2, key)) { + val1 = obj1[key]; + val2 = obj2[key]; + + // Check if both properties are pure objects and do a deep merge if so + if (vjs.obj.isPlain(val1) && vjs.obj.isPlain(val2)) { + obj1[key] = vjs.obj.deepMerge(val1, val2); + } else { + obj1[key] = obj2[key]; + } + } + } + return obj1; +}; + +/** + * Make a copy of the supplied object + * @param {Object} obj Object to copy + * @return {Object} Copy of object + */ +vjs.obj.copy = function(obj){ + return vjs.obj.merge({}, obj); +}; + +/** + * Check if an object is plain, and not a dom node or any object sub-instance + * @param {Object} obj Object to check + * @return {Boolean} True if plain, false otherwise + */ +vjs.obj.isPlain = function(obj){ + return !!obj + && typeof obj === 'object' + && obj.toString() === '[object Object]' + && obj.constructor === Object; +}; + +/** + * Bind (a.k.a proxy or Context). A simple method for changing the context of a function + It also stores a unique id on the function so it can be easily removed from events + * @param {*} context The object to bind as scope + * @param {Function} fn The function to be bound to a scope + * @param {Number=} uid An optional unique ID for the function to be set + * @return {Function} + */ +vjs.bind = function(context, fn, uid) { + // Make sure the function has a unique ID + if (!fn.guid) { fn.guid = vjs.guid++; } + + // Create the new function that changes the context + var ret = function() { + return fn.apply(context, arguments); + }; + + // Allow for the ability to individualize this function + // Needed in the case where multiple objects might share the same prototype + // IF both items add an event listener with the same function, then you try to remove just one + // it will remove both because they both have the same guid. + // when using this, you need to use the bind method when you remove the listener as well. + // currently used in text tracks + ret.guid = (uid) ? uid + '_' + fn.guid : fn.guid; + + return ret; +}; + +/** + * Element Data Store. Allows for binding data to an element without putting it directly on the element. + * Ex. Event listneres are stored here. + * (also from jsninja.com, slightly modified and updated for closure compiler) + * @type {Object} + */ +vjs.cache = {}; + +/** + * Unique ID for an element or function + * @type {Number} + */ +vjs.guid = 1; + +/** + * Unique attribute name to store an element's guid in + * @type {String} + * @constant + */ +vjs.expando = 'vdata' + (new Date()).getTime(); + +/** + * Returns the cache object where data for an element is stored + * @param {Element} el Element to store data for. + * @return {Object} + */ +vjs.getData = function(el){ + var id = el[vjs.expando]; + if (!id) { + id = el[vjs.expando] = vjs.guid++; + vjs.cache[id] = {}; + } + return vjs.cache[id]; +}; + +/** + * Returns the cache object where data for an element is stored + * @param {Element} el Element to store data for. + * @return {Object} + */ +vjs.hasData = function(el){ + var id = el[vjs.expando]; + return !(!id || vjs.isEmpty(vjs.cache[id])); +}; + +/** + * Delete data for the element from the cache and the guid attr from getElementById + * @param {Element} el Remove data for an element + */ +vjs.removeData = function(el){ + var id = el[vjs.expando]; + if (!id) { return; } + // Remove all stored data + // Changed to = null + // http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/ + // vjs.cache[id] = null; + delete vjs.cache[id]; + + // Remove the expando property from the DOM node + try { + delete el[vjs.expando]; + } catch(e) { + if (el.removeAttribute) { + el.removeAttribute(vjs.expando); + } else { + // IE doesn't appear to support removeAttribute on the document element + el[vjs.expando] = null; + } + } +}; + +vjs.isEmpty = function(obj) { + for (var prop in obj) { + // Inlude null properties as empty. + if (obj[prop] !== null) { + return false; + } + } + return true; +}; + +/** + * Add a CSS class name to an element + * @param {Element} element Element to add class name to + * @param {String} classToAdd Classname to add + */ +vjs.addClass = function(element, classToAdd){ + if ((' '+element.className+' ').indexOf(' '+classToAdd+' ') == -1) { + element.className = element.className === '' ? classToAdd : element.className + ' ' + classToAdd; + } +}; + +/** + * Remove a CSS class name from an element + * @param {Element} element Element to remove from class name + * @param {String} classToAdd Classname to remove + */ +vjs.removeClass = function(element, classToRemove){ + var classNames, i; + + if (element.className.indexOf(classToRemove) == -1) { return; } + + classNames = element.className.split(' '); + + // no arr.indexOf in ie8, and we don't want to add a big shim + for (i = classNames.length - 1; i >= 0; i--) { + if (classNames[i] === classToRemove) { + classNames.splice(i,1); + } + } + + element.className = classNames.join(' '); +}; + +/** + * Element for testing browser HTML5 video capabilities + * @type {Element} + * @constant + */ +vjs.TEST_VID = vjs.createEl('video'); + +/** + * Useragent for browser testing. + * @type {String} + * @constant + */ +vjs.USER_AGENT = navigator.userAgent; + +/** + * Device is an iPhone + * @type {Boolean} + * @constant + */ +vjs.IS_IPHONE = (/iPhone/i).test(vjs.USER_AGENT); +vjs.IS_IPAD = (/iPad/i).test(vjs.USER_AGENT); +vjs.IS_IPOD = (/iPod/i).test(vjs.USER_AGENT); +vjs.IS_IOS = vjs.IS_IPHONE || vjs.IS_IPAD || vjs.IS_IPOD; + +vjs.IOS_VERSION = (function(){ + var match = vjs.USER_AGENT.match(/OS (\d+)_/i); + if (match && match[1]) { return match[1]; } +})(); + +vjs.IS_ANDROID = (/Android/i).test(vjs.USER_AGENT); +vjs.ANDROID_VERSION = (function() { + // This matches Android Major.Minor.Patch versions + // ANDROID_VERSION is Major.Minor as a Number, if Minor isn't available, then only Major is returned + var match = vjs.USER_AGENT.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i), + major, + minor; + + if (!match) { + return null; + } + + major = match[1] && parseFloat(match[1]); + minor = match[2] && parseFloat(match[2]); + + if (major && minor) { + return parseFloat(match[1] + '.' + match[2]); + } else if (major) { + return major; + } else { + return null; + } +})(); +// Old Android is defined as Version older than 2.3, and requiring a webkit version of the android browser +vjs.IS_OLD_ANDROID = vjs.IS_ANDROID && (/webkit/i).test(vjs.USER_AGENT) && vjs.ANDROID_VERSION < 2.3; + +vjs.IS_FIREFOX = (/Firefox/i).test(vjs.USER_AGENT); +vjs.IS_CHROME = (/Chrome/i).test(vjs.USER_AGENT); + +vjs.TOUCH_ENABLED = ('ontouchstart' in window); + +/** + * Get an element's attribute values, as defined on the HTML tag + * Attributs are not the same as properties. They're defined on the tag + * or with setAttribute (which shouldn't be used with HTML) + * This will return true or false for boolean attributes. + * @param {Element} tag Element from which to get tag attributes + * @return {Object} + */ +vjs.getAttributeValues = function(tag){ + var obj, knownBooleans, attrs, attrName, attrVal; + + obj = {}; + + // known boolean attributes + // we can check for matching boolean properties, but older browsers + // won't know about HTML5 boolean attributes that we still read from + knownBooleans = ','+'autoplay,controls,loop,muted,default'+','; + + if (tag && tag.attributes && tag.attributes.length > 0) { + attrs = tag.attributes; + + for (var i = attrs.length - 1; i >= 0; i--) { + attrName = attrs[i].name; + attrVal = attrs[i].value; + + // check for known booleans + // the matching element property will return a value for typeof + if (typeof tag[attrName] === 'boolean' || knownBooleans.indexOf(','+attrName+',') !== -1) { + // the value of an included boolean attribute is typically an empty + // string ('') which would equal false if we just check for a false value. + // we also don't want support bad code like autoplay='false' + attrVal = (attrVal !== null) ? true : false; + } + + obj[attrName] = attrVal; + } + } + + return obj; +}; + +/** + * Get the computed style value for an element + * From http://robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element/ + * @param {Element} el Element to get style value for + * @param {String} strCssRule Style name + * @return {String} Style value + */ +vjs.getComputedDimension = function(el, strCssRule){ + var strValue = ''; + if(document.defaultView && document.defaultView.getComputedStyle){ + strValue = document.defaultView.getComputedStyle(el, '').getPropertyValue(strCssRule); + + } else if(el.currentStyle){ + // IE8 Width/Height support + strValue = el['client'+strCssRule.substr(0,1).toUpperCase() + strCssRule.substr(1)] + 'px'; + } + return strValue; +}; + +/** + * Insert an element as the first child node of another + * @param {Element} child Element to insert + * @param {[type]} parent Element to insert child into + */ +vjs.insertFirst = function(child, parent){ + if (parent.firstChild) { + parent.insertBefore(child, parent.firstChild); + } else { + parent.appendChild(child); + } +}; + +/** + * Object to hold browser support information + * @type {Object} + */ +vjs.support = {}; + +/** + * Shorthand for document.getElementById() + * Also allows for CSS (jQuery) ID syntax. But nothing other than IDs. + * @param {String} id Element ID + * @return {Element} Element with supplied ID + */ +vjs.el = function(id){ + if (id.indexOf('#') === 0) { + id = id.slice(1); + } + + return document.getElementById(id); +}; + +/** + * Format seconds as a time string, H:MM:SS or M:SS + * Supplying a guide (in seconds) will force a number of leading zeros + * to cover the length of the guide + * @param {Number} seconds Number of seconds to be turned into a string + * @param {Number} guide Number (in seconds) to model the string after + * @return {String} Time formatted as H:MM:SS or M:SS + */ +vjs.formatTime = function(seconds, guide) { + // Default to using seconds as guide + guide = guide || seconds; + var s = Math.floor(seconds % 60), + m = Math.floor(seconds / 60 % 60), + h = Math.floor(seconds / 3600), + gm = Math.floor(guide / 60 % 60), + gh = Math.floor(guide / 3600); + + // handle invalid times + if (isNaN(seconds) || seconds === Infinity) { + // '-' is false for all relational operators (e.g. <, >=) so this setting + // will add the minimum number of fields specified by the guide + h = m = s = '-'; + } + + // Check if we need to show hours + h = (h > 0 || gh > 0) ? h + ':' : ''; + + // If hours are showing, we may need to add a leading zero. + // Always show at least one digit of minutes. + m = (((h || gm >= 10) && m < 10) ? '0' + m : m) + ':'; + + // Check if leading zero is need for seconds + s = (s < 10) ? '0' + s : s; + + return h + m + s; +}; + +// Attempt to block the ability to select text while dragging controls +vjs.blockTextSelection = function(){ + document.body.focus(); + document.onselectstart = function () { return false; }; +}; +// Turn off text selection blocking +vjs.unblockTextSelection = function(){ document.onselectstart = function () { return true; }; }; + +/** + * Trim whitespace from the ends of a string. + * @param {String} string String to trim + * @return {String} Trimmed string + */ +vjs.trim = function(str){ + return (str+'').replace(/^\s+|\s+$/g, ''); +}; + +/** + * Should round off a number to a decimal place + * @param {Number} num Number to round + * @param {Number} dec Number of decimal places to round to + * @return {Number} Rounded number + */ +vjs.round = function(num, dec) { + if (!dec) { dec = 0; } + return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec); +}; + +/** + * Should create a fake TimeRange object + * Mimics an HTML5 time range instance, which has functions that + * return the start and end times for a range + * TimeRanges are returned by the buffered() method + * @param {Number} start Start time in seconds + * @param {Number} end End time in seconds + * @return {Object} Fake TimeRange object + */ +vjs.createTimeRange = function(start, end){ + return { + length: 1, + start: function() { return start; }, + end: function() { return end; } + }; +}; + +/** + * Simple http request for retrieving external files (e.g. text tracks) + * @param {String} url URL of resource + * @param {Function=} onSuccess Success callback + * @param {Function=} onError Error callback + */ +vjs.get = function(url, onSuccess, onError){ + var local, request; + + if (typeof XMLHttpRequest === 'undefined') { + window.XMLHttpRequest = function () { + try { return new window.ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch (e) {} + try { return new window.ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch (f) {} + try { return new window.ActiveXObject('Msxml2.XMLHTTP'); } catch (g) {} + throw new Error('This browser does not support XMLHttpRequest.'); + }; + } + + request = new XMLHttpRequest(); + try { + request.open('GET', url); + } catch(e) { + onError(e); + } + + local = (url.indexOf('file:') === 0 || (window.location.href.indexOf('file:') === 0 && url.indexOf('http') === -1)); + + request.onreadystatechange = function() { + if (request.readyState === 4) { + if (request.status === 200 || local && request.status === 0) { + onSuccess(request.responseText); + } else { + if (onError) { + onError(); + } + } + } + }; + + try { + request.send(); + } catch(e) { + if (onError) { + onError(e); + } + } +}; + +/* Local Storage +================================================================================ */ +vjs.setLocalStorage = function(key, value){ + try { + // IE was throwing errors referencing the var anywhere without this + var localStorage = window.localStorage || false; + if (!localStorage) { return; } + localStorage[key] = value; + } catch(e) { + if (e.code == 22 || e.code == 1014) { // Webkit == 22 / Firefox == 1014 + vjs.log('LocalStorage Full (VideoJS)', e); + } else { + if (e.code == 18) { + vjs.log('LocalStorage not allowed (VideoJS)', e); + } else { + vjs.log('LocalStorage Error (VideoJS)', e); + } + } + } +}; + +/** + * Get abosolute version of relative URL. Used to tell flash correct URL. + * http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue + * @param {String} url URL to make absolute + * @return {String} Absolute URL + */ +vjs.getAbsoluteURL = function(url){ + + // Check if absolute URL + if (!url.match(/^https?:\/\//)) { + // Convert to absolute URL. Flash hosted off-site needs an absolute URL. + url = vjs.createEl('div', { + innerHTML: '<a href="'+url+'">x</a>' + }).firstChild.href; + } + + return url; +}; + +// usage: log('inside coolFunc',this,arguments); +// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/ +vjs.log = function(){ + vjs.log.history = vjs.log.history || []; // store logs to an array for reference + vjs.log.history.push(arguments); + if(window.console){ + window.console.log(Array.prototype.slice.call(arguments)); + } +}; + +// Offset Left +// getBoundingClientRect technique from John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/ +vjs.findPosition = function(el) { + var box, docEl, body, clientLeft, scrollLeft, left, clientTop, scrollTop, top; + + if (el.getBoundingClientRect && el.parentNode) { + box = el.getBoundingClientRect(); + } + + if (!box) { + return { + left: 0, + top: 0 + }; + } + + docEl = document.documentElement; + body = document.body; + + clientLeft = docEl.clientLeft || body.clientLeft || 0; + scrollLeft = window.pageXOffset || body.scrollLeft; + left = box.left + scrollLeft - clientLeft; + + clientTop = docEl.clientTop || body.clientTop || 0; + scrollTop = window.pageYOffset || body.scrollTop; + top = box.top + scrollTop - clientTop; + + return { + left: left, + top: top + }; +}; +/** + * @fileoverview Player Component - Base class for all UI objects + * + */ + +/** + * Base UI Component class + * @param {Object} player Main Player + * @param {Object=} options + * @constructor + */ +vjs.Component = vjs.CoreObject.extend({ + /** @constructor */ + init: function(player, options, ready){ + this.player_ = player; + + // Make a copy of prototype.options_ to protect against overriding global defaults + this.options_ = vjs.obj.copy(this.options_); + + // Updated options with supplied options + options = this.options(options); + + // Get ID from options, element, or create using player ID and unique ID + this.id_ = options['id'] || ((options['el'] && options['el']['id']) ? options['el']['id'] : player.id() + '_component_' + vjs.guid++ ); + + this.name_ = options['name'] || null; + + // Create element if one wasn't provided in options + this.el_ = options['el'] || this.createEl(); + + this.children_ = []; + this.childIndex_ = {}; + this.childNameIndex_ = {}; + + // Add any child components in options + this.initChildren(); + + this.ready(ready); + // Don't want to trigger ready here or it will before init is actually + // finished for all children that run this constructor + } +}); + +/** + * Dispose of the component and all child components. + */ +vjs.Component.prototype.dispose = function(){ + this.trigger('dispose'); + + // Dispose all children. + if (this.children_) { + for (var i = this.children_.length - 1; i >= 0; i--) { + if (this.children_[i].dispose) { + this.children_[i].dispose(); + } + } + } + + // Delete child references + this.children_ = null; + this.childIndex_ = null; + this.childNameIndex_ = null; + + // Remove all event listeners. + this.off(); + + // Remove element from DOM + if (this.el_.parentNode) { + this.el_.parentNode.removeChild(this.el_); + } + + vjs.removeData(this.el_); + this.el_ = null; +}; + +/** + * Reference to main player instance. + * @type {vjs.Player} + * @private + */ +vjs.Component.prototype.player_; + +/** + * Return the component's player. + * @return {vjs.Player} + */ +vjs.Component.prototype.player = function(){ + return this.player_; +}; + +/** + * Component options object. + * @type {Object} + * @private + */ +vjs.Component.prototype.options_; + +/** + * Deep merge of options objects + * Whenever a property is an object on both options objects + * the two properties will be merged using vjs.obj.deepMerge. + * + * This is used for merging options for child components. We + * want it to be easy to override individual options on a child + * component without having to rewrite all the other default options. + * + * Parent.prototype.options_ = { + * children: { + * 'childOne': { 'foo': 'bar', 'asdf': 'fdsa' }, + * 'childTwo': {}, + * 'childThree': {} + * } + * } + * newOptions = { + * children: { + * 'childOne': { 'foo': 'baz', 'abc': '123' } + * 'childTwo': null, + * 'childFour': {} + * } + * } + * + * this.options(newOptions); + * + * RESULT + * + * { + * children: { + * 'childOne': { 'foo': 'baz', 'asdf': 'fdsa', 'abc': '123' }, + * 'childTwo': null, // Disabled. Won't be initialized. + * 'childThree': {}, + * 'childFour': {} + * } + * } + * + * @param {Object} obj Object whose values will be overwritten + * @return {Object} NEW merged object. Does not return obj1. + */ +vjs.Component.prototype.options = function(obj){ + if (obj === undefined) return this.options_; + + return this.options_ = vjs.obj.deepMerge(this.options_, obj); +}; + +/** + * The DOM element for the component. + * @type {Element} + * @private + */ +vjs.Component.prototype.el_; + +/** + * Create the component's DOM element. + * @param {String=} tagName Element's node type. e.g. 'div' + * @param {Object=} attributes An object of element attributes that should be set on the element. + * @return {Element} + */ +vjs.Component.prototype.createEl = function(tagName, attributes){ + return vjs.createEl(tagName, attributes); +}; + +/** + * Return the component's DOM element. + * @return {Element} + */ +vjs.Component.prototype.el = function(){ + return this.el_; +}; + +/** + * An optional element where, if defined, children will be inserted + * instead of directly in el_ + * @type {Element} + * @private + */ +vjs.Component.prototype.contentEl_; + +/** + * Return the component's DOM element for embedding content. + * will either be el_ or a new element defined in createEl + * @return {Element} + */ +vjs.Component.prototype.contentEl = function(){ + return this.contentEl_ || this.el_; +}; + +/** + * The ID for the component. + * @type {String} + * @private + */ +vjs.Component.prototype.id_; + +/** + * Return the component's ID. + * @return {String} + */ +vjs.Component.prototype.id = function(){ + return this.id_; +}; + +/** + * The name for the component. Often used to reference the component. + * @type {String} + * @private + */ +vjs.Component.prototype.name_; + +/** + * Return the component's ID. + * @return {String} + */ +vjs.Component.prototype.name = function(){ + return this.name_; +}; + +/** + * Array of child components + * @type {Array} + * @private + */ +vjs.Component.prototype.children_; + +/** + * Returns array of all child components. + * @return {Array} + */ +vjs.Component.prototype.children = function(){ + return this.children_; +}; + +/** + * Object of child components by ID + * @type {Object} + * @private + */ +vjs.Component.prototype.childIndex_; + +/** + * Returns a child component with the provided ID. + * @return {Array} + */ +vjs.Component.prototype.getChildById = function(id){ + return this.childIndex_[id]; +}; + +/** + * Object of child components by Name + * @type {Object} + * @private + */ +vjs.Component.prototype.childNameIndex_; + +/** + * Returns a child component with the provided ID. + * @return {Array} + */ +vjs.Component.prototype.getChild = function(name){ + return this.childNameIndex_[name]; +}; + +/** + * Adds a child component inside this component. + * @param {String|vjs.Component} child The class name or instance of a child to add. + * @param {Object=} options Optional options, including options to be passed to + * children of the child. + * @return {vjs.Component} The child component, because it might be created in this process. + * @suppress {accessControls|checkRegExp|checkTypes|checkVars|const|constantProperty|deprecated|duplicate|es5Strict|fileoverviewTags|globalThis|invalidCasts|missingProperties|nonStandardJsDocs|strictModuleDepCheck|undefinedNames|undefinedVars|unknownDefines|uselessCode|visibility} + */ +vjs.Component.prototype.addChild = function(child, options){ + var component, componentClass, componentName, componentId; + + // If string, create new component with options + if (typeof child === 'string') { + + componentName = child; + + // Make sure options is at least an empty object to protect against errors + options = options || {}; + + // Assume name of set is a lowercased name of the UI Class (PlayButton, etc.) + componentClass = options['componentClass'] || vjs.capitalize(componentName); + + // Set name through options + options['name'] = componentName; + + // Create a new object & element for this controls set + // If there's no .player_, this is a player + // Closure Compiler throws an 'incomplete alias' warning if we use the vjs variable directly. + // Every class should be exported, so this should never be a problem here. + component = new window['videojs'][componentClass](this.player_ || this, options); + + // child is a component instance + } else { + component = child; + } + + this.children_.push(component); + + if (typeof component.id === 'function') { + this.childIndex_[component.id()] = component; + } + + // If a name wasn't used to create the component, check if we can use the + // name function of the component + componentName = componentName || (component.name && component.name()); + + if (componentName) { + this.childNameIndex_[componentName] = component; + } + + // Add the UI object's element to the container div (box) + // Having an element is not required + if (typeof component['el'] === 'function' && component['el']()) { + this.contentEl().appendChild(component['el']()); + } + + // Return so it can stored on parent object if desired. + return component; +}; + +vjs.Component.prototype.removeChild = function(component){ + if (typeof component === 'string') { + component = this.getChild(component); + } + + if (!component || !this.children_) return; + + var childFound = false; + for (var i = this.children_.length - 1; i >= 0; i--) { + if (this.children_[i] === component) { + childFound = true; + this.children_.splice(i,1); + break; + } + } + + if (!childFound) return; + + this.childIndex_[component.id] = null; + this.childNameIndex_[component.name] = null; + + var compEl = component.el(); + if (compEl && compEl.parentNode === this.contentEl()) { + this.contentEl().removeChild(component.el()); + } +}; + +/** + * Initialize default child components from options + */ +vjs.Component.prototype.initChildren = function(){ + var options = this.options_; + + if (options && options['children']) { + var self = this; + + // Loop through components and add them to the player + vjs.obj.each(options['children'], function(name, opts){ + // Allow for disabling default components + // e.g. vjs.options['children']['posterImage'] = false + if (opts === false) return; + + // Allow waiting to add components until a specific event is called + var tempAdd = function(){ + // Set property name on player. Could cause conflicts with other prop names, but it's worth making refs easy. + self[name] = self.addChild(name, opts); + }; + + if (opts['loadEvent']) { + // this.one(opts.loadEvent, tempAdd) + } else { + tempAdd(); + } + }); + } +}; + +vjs.Component.prototype.buildCSSClass = function(){ + // Child classes can include a function that does: + // return 'CLASS NAME' + this._super(); + return ''; +}; + +/* Events +============================================================================= */ + +/** + * Add an event listener to this component's element. Context will be the component. + * @param {String} type Event type e.g. 'click' + * @param {Function} fn Event listener + * @return {vjs.Component} + */ +vjs.Component.prototype.on = function(type, fn){ + vjs.on(this.el_, type, vjs.bind(this, fn)); + return this; +}; + +/** + * Remove an event listener from the component's element + * @param {String=} type Optional event type. Without type it will remove all listeners. + * @param {Function=} fn Optional event listener. Without fn it will remove all listeners for a type. + * @return {vjs.Component} + */ +vjs.Component.prototype.off = function(type, fn){ + vjs.off(this.el_, type, fn); + return this; +}; + +/** + * Add an event listener to be triggered only once and then removed + * @param {String} type Event type + * @param {Function} fn Event listener + * @return {vjs.Component} + */ +vjs.Component.prototype.one = function(type, fn) { + vjs.one(this.el_, type, vjs.bind(this, fn)); + return this; +}; + +/** + * Trigger an event on an element + * @param {String} type Event type to trigger + * @param {Event|Object} event Event object to be passed to the listener + * @return {vjs.Component} + */ +vjs.Component.prototype.trigger = function(type, event){ + vjs.trigger(this.el_, type, event); + return this; +}; + +/* Ready +================================================================================ */ +/** + * Is the component loaded. + * @type {Boolean} + * @private + */ +vjs.Component.prototype.isReady_; + +/** + * Trigger ready as soon as initialization is finished. + * Allows for delaying ready. Override on a sub class prototype. + * If you set this.isReadyOnInitFinish_ it will affect all components. + * Specially used when waiting for the Flash player to asynchrnously load. + * @type {Boolean} + * @private + */ +vjs.Component.prototype.isReadyOnInitFinish_ = true; + +/** + * List of ready listeners + * @type {Array} + * @private + */ +vjs.Component.prototype.readyQueue_; + +/** + * Bind a listener to the component's ready state. + * Different from event listeners in that if the ready event has already happend + * it will trigger the function immediately. + * @param {Function} fn Ready listener + * @return {vjs.Component} + */ +vjs.Component.prototype.ready = function(fn){ + if (fn) { + if (this.isReady_) { + fn.call(this); + } else { + if (this.readyQueue_ === undefined) { + this.readyQueue_ = []; + } + this.readyQueue_.push(fn); + } + } + return this; +}; + +/** + * Trigger the ready listeners + * @return {vjs.Component} + */ +vjs.Component.prototype.triggerReady = function(){ + this.isReady_ = true; + + var readyQueue = this.readyQueue_; + + if (readyQueue && readyQueue.length > 0) { + + for (var i = 0, j = readyQueue.length; i < j; i++) { + readyQueue[i].call(this); + } + + // Reset Ready Queue + this.readyQueue_ = []; + + // Allow for using event listeners also, in case you want to do something everytime a source is ready. + this.trigger('ready'); + } +}; + +/* Display +============================================================================= */ + +/** + * Add a CSS class name to the component's element + * @param {String} classToAdd Classname to add + * @return {vjs.Component} + */ +vjs.Component.prototype.addClass = function(classToAdd){ + vjs.addClass(this.el_, classToAdd); + return this; +}; + +/** + * Remove a CSS class name from the component's element + * @param {String} classToRemove Classname to remove + * @return {vjs.Component} + */ +vjs.Component.prototype.removeClass = function(classToRemove){ + vjs.removeClass(this.el_, classToRemove); + return this; +}; + +/** + * Show the component element if hidden + * @return {vjs.Component} + */ +vjs.Component.prototype.show = function(){ + this.el_.style.display = 'block'; + return this; +}; + +/** + * Hide the component element if hidden + * @return {vjs.Component} + */ +vjs.Component.prototype.hide = function(){ + this.el_.style.display = 'none'; + return this; +}; + +/** + * Lock an item in its visible state. To be used with fadeIn/fadeOut. + * @return {vjs.Component} + */ +vjs.Component.prototype.lockShowing = function(){ + this.addClass('vjs-lock-showing'); + return this; +}; + +/** + * Unlock an item to be hidden. To be used with fadeIn/fadeOut. + * @return {vjs.Component} + */ +vjs.Component.prototype.unlockShowing = function(){ + this.removeClass('vjs-lock-showing'); + return this; +}; + +/** + * Disable component by making it unshowable + */ +vjs.Component.prototype.disable = function(){ + this.hide(); + this.show = function(){}; +}; + +/** + * If a value is provided it will change the width of the player to that value + * otherwise the width is returned + * http://dev.w3.org/html5/spec/dimension-attributes.html#attr-dim-height + * Video tag width/height only work in pixels. No percents. + * But allowing limited percents use. e.g. width() will return number+%, not computed width + * @param {Number|String=} num Optional width number + * @param {[type]} skipListeners Skip the 'resize' event trigger + * @return {vjs.Component|Number|String} Returns 'this' if dimension was set. + * Otherwise it returns the dimension. + */ +vjs.Component.prototype.width = function(num, skipListeners){ + return this.dimension('width', num, skipListeners); +}; + +/** + * Get or set the height of the player + * @param {Number|String=} num Optional new player height + * @param {Boolean=} skipListeners Optional skip resize event trigger + * @return {vjs.Component|Number|String} The player, or the dimension + */ +vjs.Component.prototype.height = function(num, skipListeners){ + return this.dimension('height', num, skipListeners); +}; + +/** + * Set both width and height at the same time. + * @param {Number|String} width + * @param {Number|String} height + * @return {vjs.Component} The player. + */ +vjs.Component.prototype.dimensions = function(width, height){ + // Skip resize listeners on width for optimization + return this.width(width, true).height(height); +}; + +/** + * Get or set width or height. + * All for an integer, integer + 'px' or integer + '%'; + * Known issue: hidden elements. Hidden elements officially have a width of 0. + * So we're defaulting to the style.width value and falling back to computedStyle + * which has the hidden element issue. + * Info, but probably not an efficient fix: + * http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/ + * @param {String=} widthOrHeight 'width' or 'height' + * @param {Number|String=} num New dimension + * @param {Boolean=} skipListeners Skip resize event trigger + * @return {vjs.Component|Number|String} Return the player if setting a dimension. + * Otherwise it returns the dimension. + */ +vjs.Component.prototype.dimension = function(widthOrHeight, num, skipListeners){ + if (num !== undefined) { + + // Check if using css width/height (% or px) and adjust + if ((''+num).indexOf('%') !== -1 || (''+num).indexOf('px') !== -1) { + this.el_.style[widthOrHeight] = num; + } else if (num === 'auto') { + this.el_.style[widthOrHeight] = ''; + } else { + this.el_.style[widthOrHeight] = num+'px'; + } + + // skipListeners allows us to avoid triggering the resize event when setting both width and height + if (!skipListeners) { this.trigger('resize'); } + + // Return component + return this; + } + + // Not setting a value, so getting it + // Make sure element exists + if (!this.el_) return 0; + + // Get dimension value from style + var val = this.el_.style[widthOrHeight]; + var pxIndex = val.indexOf('px'); + if (pxIndex !== -1) { + // Return the pixel value with no 'px' + return parseInt(val.slice(0,pxIndex), 10); + + // No px so using % or no style was set, so falling back to offsetWidth/height + // If component has display:none, offset will return 0 + // TODO: handle display:none and no dimension style using px + } else { + + return parseInt(this.el_['offset'+vjs.capitalize(widthOrHeight)], 10); + + // ComputedStyle version. + // Only difference is if the element is hidden it will return + // the percent value (e.g. '100%'') + // instead of zero like offsetWidth returns. + // var val = vjs.getComputedStyleValue(this.el_, widthOrHeight); + // var pxIndex = val.indexOf('px'); + + // if (pxIndex !== -1) { + // return val.slice(0, pxIndex); + // } else { + // return val; + // } + } +}; + +/** + * Emit 'tap' events when touch events are supported. We're requireing them to + * be enabled because otherwise every component would have this extra overhead + * unnecessarily, on mobile devices where extra overhead is especially bad. + * + * This is being implemented so we can support taps on the video element + * toggling the controls. + */ +vjs.Component.prototype.emitTapEvents = function(){ + var touchStart, touchTime, couldBeTap, noTap; + + // Track the start time so we can determine how long the touch lasted + touchStart = 0; + + this.on('touchstart', function(event) { + // Record start time so we can detect a tap vs. "touch and hold" + touchStart = new Date().getTime(); + // Reset couldBeTap tracking + couldBeTap = true; + }); + + noTap = function(){ + couldBeTap = false; + }; + // TODO: Listen to the original target. http://youtu.be/DujfpXOKUp8?t=13m8s + this.on('touchmove', noTap); + this.on('touchleave', noTap); + this.on('touchcancel', noTap); + + // When the touch ends, measure how long it took and trigger the appropriate + // event + this.on('touchend', function() { + // Proceed only if the touchmove/leave/cancel event didn't happen + if (couldBeTap === true) { + // Measure how long the touch lasted + touchTime = new Date().getTime() - touchStart; + // The touch needs to be quick in order to consider it a tap + if (touchTime < 250) { + this.trigger('tap'); + // It may be good to copy the touchend event object and change the + // type to tap, if the other event properties aren't exact after + // vjs.fixEvent runs (e.g. event.target) + } + } + }); +}; +/* Button - Base class for all buttons +================================================================================ */ +/** + * Base class for all buttons + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.Button = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + + var touchstart = false; + this.on('touchstart', function(event) { + // Stop click and other mouse events from triggering also + event.preventDefault(); + touchstart = true; + }); + this.on('touchmove', function() { + touchstart = false; + }); + var self = this; + this.on('touchend', function(event) { + if (touchstart) { + self.onClick(event); + } + event.preventDefault(); + }); + + this.on('click', this.onClick); + this.on('focus', this.onFocus); + this.on('blur', this.onBlur); + } +}); + +vjs.Button.prototype.createEl = function(type, props){ + // Add standard Aria and Tabindex info + props = vjs.obj.merge({ + className: this.buildCSSClass(), + innerHTML: '<div class="vjs-control-content"><span class="vjs-control-text">' + (this.buttonText || 'Need Text') + '</span></div>', + role: 'button', + 'aria-live': 'polite', // let the screen reader user know that the text of the button may change + tabIndex: 0 + }, props); + + return vjs.Component.prototype.createEl.call(this, type, props); +}; + +vjs.Button.prototype.buildCSSClass = function(){ + // TODO: Change vjs-control to vjs-button? + return 'vjs-control ' + vjs.Component.prototype.buildCSSClass.call(this); +}; + + // Click - Override with specific functionality for button +vjs.Button.prototype.onClick = function(){}; + + // Focus - Add keyboard functionality to element +vjs.Button.prototype.onFocus = function(){ + vjs.on(document, 'keyup', vjs.bind(this, this.onKeyPress)); +}; + + // KeyPress (document level) - Trigger click when keys are pressed +vjs.Button.prototype.onKeyPress = function(event){ + // Check for space bar (32) or enter (13) keys + if (event.which == 32 || event.which == 13) { + event.preventDefault(); + this.onClick(); + } +}; + +// Blur - Remove keyboard triggers +vjs.Button.prototype.onBlur = function(){ + vjs.off(document, 'keyup', vjs.bind(this, this.onKeyPress)); +}; +/* Slider +================================================================================ */ +/** + * Parent for seek bar and volume slider + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.Slider = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + + // Set property names to bar and handle to match with the child Slider class is looking for + this.bar = this.getChild(this.options_['barName']); + this.handle = this.getChild(this.options_['handleName']); + + player.on(this.playerEvent, vjs.bind(this, this.update)); + + this.on('mousedown', this.onMouseDown); + this.on('touchstart', this.onMouseDown); + this.on('focus', this.onFocus); + this.on('blur', this.onBlur); + this.on('click', this.onClick); + + this.player_.on('controlsvisible', vjs.bind(this, this.update)); + + // This is actually to fix the volume handle position. http://twitter.com/#!/gerritvanaaken/status/159046254519787520 + // this.player_.one('timeupdate', vjs.bind(this, this.update)); + + player.ready(vjs.bind(this, this.update)); + + this.boundEvents = {}; + } +}); + +vjs.Slider.prototype.createEl = function(type, props) { + props = props || {}; + // Add the slider element class to all sub classes + props.className = props.className + ' vjs-slider'; + props = vjs.obj.merge({ + role: 'slider', + 'aria-valuenow': 0, + 'aria-valuemin': 0, + 'aria-valuemax': 100, + tabIndex: 0 + }, props); + + return vjs.Component.prototype.createEl.call(this, type, props); +}; + +vjs.Slider.prototype.onMouseDown = function(event){ + event.preventDefault(); + vjs.blockTextSelection(); + + this.boundEvents.move = vjs.bind(this, this.onMouseMove); + this.boundEvents.end = vjs.bind(this, this.onMouseUp); + + vjs.on(document, 'mousemove', this.boundEvents.move); + vjs.on(document, 'mouseup', this.boundEvents.end); + vjs.on(document, 'touchmove', this.boundEvents.move); + vjs.on(document, 'touchend', this.boundEvents.end); + + this.onMouseMove(event); +}; + +vjs.Slider.prototype.onMouseUp = function() { + vjs.unblockTextSelection(); + vjs.off(document, 'mousemove', this.boundEvents.move, false); + vjs.off(document, 'mouseup', this.boundEvents.end, false); + vjs.off(document, 'touchmove', this.boundEvents.move, false); + vjs.off(document, 'touchend', this.boundEvents.end, false); + + this.update(); +}; + +vjs.Slider.prototype.update = function(){ + // In VolumeBar init we have a setTimeout for update that pops and update to the end of the + // execution stack. The player is destroyed before then update will cause an error + if (!this.el_) return; + + // If scrubbing, we could use a cached value to make the handle keep up with the user's mouse. + // On HTML5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later. + // var progress = (this.player_.scrubbing) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration(); + + var barProgress, + progress = this.getPercent(), + handle = this.handle, + bar = this.bar; + + // Protect against no duration and other division issues + if (isNaN(progress)) { progress = 0; } + + barProgress = progress; + + // If there is a handle, we need to account for the handle in our calculation for progress bar + // so that it doesn't fall short of or extend past the handle. + if (handle) { + + var box = this.el_, + boxWidth = box.offsetWidth, + + handleWidth = handle.el().offsetWidth, + + // The width of the handle in percent of the containing box + // In IE, widths may not be ready yet causing NaN + handlePercent = (handleWidth) ? handleWidth / boxWidth : 0, + + // Get the adjusted size of the box, considering that the handle's center never touches the left or right side. + // There is a margin of half the handle's width on both sides. + boxAdjustedPercent = 1 - handlePercent, + + // Adjust the progress that we'll use to set widths to the new adjusted box width + adjustedProgress = progress * boxAdjustedPercent; + + // The bar does reach the left side, so we need to account for this in the bar's width + barProgress = adjustedProgress + (handlePercent / 2); + + // Move the handle from the left based on the adjected progress + handle.el().style.left = vjs.round(adjustedProgress * 100, 2) + '%'; + } + + // Set the new bar width + bar.el().style.width = vjs.round(barProgress * 100, 2) + '%'; +}; + +vjs.Slider.prototype.calculateDistance = function(event){ + var el, box, boxX, boxY, boxW, boxH, handle, pageX, pageY; + + el = this.el_; + box = vjs.findPosition(el); + boxW = boxH = el.offsetWidth; + handle = this.handle; + + if (this.options_.vertical) { + boxY = box.top; + + if (event.changedTouches) { + pageY = event.changedTouches[0].pageY; + } else { + pageY = event.pageY; + } + + if (handle) { + var handleH = handle.el().offsetHeight; + // Adjusted X and Width, so handle doesn't go outside the bar + boxY = boxY + (handleH / 2); + boxH = boxH - handleH; + } + + // Percent that the click is through the adjusted area + return Math.max(0, Math.min(1, ((boxY - pageY) + boxH) / boxH)); + + } else { + boxX = box.left; + + if (event.changedTouches) { + pageX = event.changedTouches[0].pageX; + } else { + pageX = event.pageX; + } + + if (handle) { + var handleW = handle.el().offsetWidth; + + // Adjusted X and Width, so handle doesn't go outside the bar + boxX = boxX + (handleW / 2); + boxW = boxW - handleW; + } + + // Percent that the click is through the adjusted area + return Math.max(0, Math.min(1, (pageX - boxX) / boxW)); + } +}; + +vjs.Slider.prototype.onFocus = function(){ + vjs.on(document, 'keyup', vjs.bind(this, this.onKeyPress)); +}; + +vjs.Slider.prototype.onKeyPress = function(event){ + if (event.which == 37) { // Left Arrow + event.preventDefault(); + this.stepBack(); + } else if (event.which == 39) { // Right Arrow + event.preventDefault(); + this.stepForward(); + } +}; + +vjs.Slider.prototype.onBlur = function(){ + vjs.off(document, 'keyup', vjs.bind(this, this.onKeyPress)); +}; + +/** + * Listener for click events on slider, used to prevent clicks + * from bubbling up to parent elements like button menus. + * @param {Object} event Event object + */ +vjs.Slider.prototype.onClick = function(event){ + event.stopImmediatePropagation(); + event.preventDefault(); +}; + +/** + * SeekBar Behavior includes play progress bar, and seek handle + * Needed so it can determine seek position based on handle position/size + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.SliderHandle = vjs.Component.extend(); + +/** + * Default value of the slider + * @type {Number} + */ +vjs.SliderHandle.prototype.defaultValue = 0; + +/** @inheritDoc */ +vjs.SliderHandle.prototype.createEl = function(type, props) { + props = props || {}; + // Add the slider element class to all sub classes + props.className = props.className + ' vjs-slider-handle'; + props = vjs.obj.merge({ + innerHTML: '<span class="vjs-control-text">'+this.defaultValue+'</span>' + }, props); + + return vjs.Component.prototype.createEl.call(this, 'div', props); +}; +/* Menu +================================================================================ */ +/** + * The base for text track and settings menu buttons. + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.Menu = vjs.Component.extend(); + +/** + * Add a menu item to the menu + * @param {Object|String} component Component or component type to add + */ +vjs.Menu.prototype.addItem = function(component){ + this.addChild(component); + component.on('click', vjs.bind(this, function(){ + this.unlockShowing(); + })); +}; + +/** @inheritDoc */ +vjs.Menu.prototype.createEl = function(){ + var contentElType = this.options().contentElType || 'ul'; + this.contentEl_ = vjs.createEl(contentElType, { + className: 'vjs-menu-content' + }); + var el = vjs.Component.prototype.createEl.call(this, 'div', { + append: this.contentEl_, + className: 'vjs-menu' + }); + el.appendChild(this.contentEl_); + + // Prevent clicks from bubbling up. Needed for Menu Buttons, + // where a click on the parent is significant + vjs.on(el, 'click', function(event){ + event.preventDefault(); + event.stopImmediatePropagation(); + }); + + return el; +}; + +/** + * Menu item + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.MenuItem = vjs.Button.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Button.call(this, player, options); + this.selected(options['selected']); + } +}); + +/** @inheritDoc */ +vjs.MenuItem.prototype.createEl = function(type, props){ + return vjs.Button.prototype.createEl.call(this, 'li', vjs.obj.merge({ + className: 'vjs-menu-item', + innerHTML: this.options_['label'] + }, props)); +}; + +/** @inheritDoc */ +vjs.MenuItem.prototype.onClick = function(){ + this.selected(true); +}; + +/** + * Set this menu item as selected or not + * @param {Boolean} selected + */ +vjs.MenuItem.prototype.selected = function(selected){ + if (selected) { + this.addClass('vjs-selected'); + this.el_.setAttribute('aria-selected',true); + } else { + this.removeClass('vjs-selected'); + this.el_.setAttribute('aria-selected',false); + } +}; + + +/** + * A button class with a popup menu + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.MenuButton = vjs.Button.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Button.call(this, player, options); + + this.menu = this.createMenu(); + + // Add list to element + this.addChild(this.menu); + + // Automatically hide empty menu buttons + if (this.items && this.items.length === 0) { + this.hide(); + } + + this.on('keyup', this.onKeyPress); + this.el_.setAttribute('aria-haspopup', true); + this.el_.setAttribute('role', 'button'); + } +}); + +/** + * Track the state of the menu button + * @type {Boolean} + */ +vjs.MenuButton.prototype.buttonPressed_ = false; + +vjs.MenuButton.prototype.createMenu = function(){ + var menu = new vjs.Menu(this.player_); + + // Add a title list item to the top + if (this.options().title) { + menu.el().appendChild(vjs.createEl('li', { + className: 'vjs-menu-title', + innerHTML: vjs.capitalize(this.kind_), + tabindex: -1 + })); + } + + this.items = this['createItems'](); + + if (this.items) { + // Add menu items to the menu + for (var i = 0; i < this.items.length; i++) { + menu.addItem(this.items[i]); + } + } + + return menu; +}; + +/** + * Create the list of menu items. Specific to each subclass. + */ +vjs.MenuButton.prototype.createItems = function(){}; + +/** @inheritDoc */ +vjs.MenuButton.prototype.buildCSSClass = function(){ + return this.className + ' vjs-menu-button ' + vjs.Button.prototype.buildCSSClass.call(this); +}; + +// Focus - Add keyboard functionality to element +// This function is not needed anymore. Instead, the keyboard functionality is handled by +// treating the button as triggering a submenu. When the button is pressed, the submenu +// appears. Pressing the button again makes the submenu disappear. +vjs.MenuButton.prototype.onFocus = function(){}; +// Can't turn off list display that we turned on with focus, because list would go away. +vjs.MenuButton.prototype.onBlur = function(){}; + +vjs.MenuButton.prototype.onClick = function(){ + // When you click the button it adds focus, which will show the menu indefinitely. + // So we'll remove focus when the mouse leaves the button. + // Focus is needed for tab navigation. + this.one('mouseout', vjs.bind(this, function(){ + this.menu.unlockShowing(); + this.el_.blur(); + })); + if (this.buttonPressed_){ + this.unpressButton(); + } else { + this.pressButton(); + } +}; + +vjs.MenuButton.prototype.onKeyPress = function(event){ + event.preventDefault(); + + // Check for space bar (32) or enter (13) keys + if (event.which == 32 || event.which == 13) { + if (this.buttonPressed_){ + this.unpressButton(); + } else { + this.pressButton(); + } + // Check for escape (27) key + } else if (event.which == 27){ + if (this.buttonPressed_){ + this.unpressButton(); + } + } +}; + +vjs.MenuButton.prototype.pressButton = function(){ + this.buttonPressed_ = true; + this.menu.lockShowing(); + this.el_.setAttribute('aria-pressed', true); + if (this.items && this.items.length > 0) { + this.items[0].el().focus(); // set the focus to the title of the submenu + } +}; + +vjs.MenuButton.prototype.unpressButton = function(){ + this.buttonPressed_ = false; + this.menu.unlockShowing(); + this.el_.setAttribute('aria-pressed', false); +}; + +/** + * Main player class. A player instance is returned by _V_(id); + * @param {Element} tag The original video tag used for configuring options + * @param {Object=} options Player options + * @param {Function=} ready Ready callback function + * @constructor + */ +vjs.Player = vjs.Component.extend({ + /** @constructor */ + init: function(tag, options, ready){ + this.tag = tag; // Store the original tag used to set options + + // Set Options + // The options argument overrides options set in the video tag + // which overrides globally set options. + // This latter part coincides with the load order + // (tag must exist before Player) + options = vjs.obj.merge(this.getTagSettings(tag), options); + + // Cache for video property values. + this.cache_ = {}; + + // Set poster + this.poster_ = options['poster']; + // Set controls + this.controls_ = options['controls']; + // Original tag settings stored in options + // now remove immediately so native controls don't flash. + // May be turned back on by HTML5 tech if nativeControlsForTouch is true + tag.controls = false; + + // Run base component initializing with new options. + // Builds the element through createEl() + // Inits and embeds any child components in opts + vjs.Component.call(this, this, options, ready); + + // Update controls className. Can't do this when the controls are initially + // set because the element doesn't exist yet. + if (this.controls()) { + this.addClass('vjs-controls-enabled'); + } else { + this.addClass('vjs-controls-disabled'); + } + + // TODO: Make this smarter. Toggle user state between touching/mousing + // using events, since devices can have both touch and mouse events. + // if (vjs.TOUCH_ENABLED) { + // this.addClass('vjs-touch-enabled'); + // } + + // Firstplay event implimentation. Not sold on the event yet. + // Could probably just check currentTime==0? + this.one('play', function(e){ + var fpEvent = { type: 'firstplay', target: this.el_ }; + // Using vjs.trigger so we can check if default was prevented + var keepGoing = vjs.trigger(this.el_, fpEvent); + + if (!keepGoing) { + e.preventDefault(); + e.stopPropagation(); + e.stopImmediatePropagation(); + } + }); + + this.on('ended', this.onEnded); + this.on('play', this.onPlay); + this.on('firstplay', this.onFirstPlay); + this.on('pause', this.onPause); + this.on('progress', this.onProgress); + this.on('durationchange', this.onDurationChange); + this.on('error', this.onError); + this.on('fullscreenchange', this.onFullscreenChange); + + // Make player easily findable by ID + vjs.players[this.id_] = this; + + if (options['plugins']) { + vjs.obj.each(options['plugins'], function(key, val){ + this[key](val); + }, this); + } + + this.listenForUserActivity(); + } +}); + +/** + * Player instance options, surfaced using vjs.options + * vjs.options = vjs.Player.prototype.options_ + * Make changes in vjs.options, not here. + * All options should use string keys so they avoid + * renaming by closure compiler + * @type {Object} + * @private + */ +vjs.Player.prototype.options_ = vjs.options; + +vjs.Player.prototype.dispose = function(){ + this.trigger('dispose'); + // prevent dispose from being called twice + this.off('dispose'); + + // Kill reference to this player + vjs.players[this.id_] = null; + if (this.tag && this.tag['player']) { this.tag['player'] = null; } + if (this.el_ && this.el_['player']) { this.el_['player'] = null; } + + // Ensure that tracking progress and time progress will stop and plater deleted + this.stopTrackingProgress(); + this.stopTrackingCurrentTime(); + + if (this.tech) { this.tech.dispose(); } + + // Component dispose + vjs.Component.prototype.dispose.call(this); +}; + +vjs.Player.prototype.getTagSettings = function(tag){ + var options = { + 'sources': [], + 'tracks': [] + }; + + vjs.obj.merge(options, vjs.getAttributeValues(tag)); + + // Get tag children settings + if (tag.hasChildNodes()) { + var children, child, childName, i, j; + + children = tag.childNodes; + + for (i=0,j=children.length; i<j; i++) { + child = children[i]; + // Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/ + childName = child.nodeName.toLowerCase(); + if (childName === 'source') { + options['sources'].push(vjs.getAttributeValues(child)); + } else if (childName === 'track') { + options['tracks'].push(vjs.getAttributeValues(child)); + } + } + } + + return options; +}; + +vjs.Player.prototype.createEl = function(){ + var el = this.el_ = vjs.Component.prototype.createEl.call(this, 'div'); + var tag = this.tag; + + // Remove width/height attrs from tag so CSS can make it 100% width/height + tag.removeAttribute('width'); + tag.removeAttribute('height'); + // Empty video tag sources and tracks so the built-in player doesn't use them also. + // This may not be fast enough to stop HTML5 browsers from reading the tags + // so we'll need to turn off any default tracks if we're manually doing + // captions and subtitles. videoElement.textTracks + if (tag.hasChildNodes()) { + var nodes, nodesLength, i, node, nodeName, removeNodes; + + nodes = tag.childNodes; + nodesLength = nodes.length; + removeNodes = []; + + while (nodesLength--) { + node = nodes[nodesLength]; + nodeName = node.nodeName.toLowerCase(); + if (nodeName === 'source' || nodeName === 'track') { + removeNodes.push(node); + } + } + + for (i=0; i<removeNodes.length; i++) { + tag.removeChild(removeNodes[i]); + } + } + + // Make sure tag ID exists + tag.id = tag.id || 'vjs_video_' + vjs.guid++; + + // Give video tag ID and class to player div + // ID will now reference player box, not the video tag + el.id = tag.id; + el.className = tag.className; + + // Update tag id/class for use as HTML5 playback tech + // Might think we should do this after embedding in container so .vjs-tech class + // doesn't flash 100% width/height, but class only applies with .video-js parent + tag.id += '_html5_api'; + tag.className = 'vjs-tech'; + + // Make player findable on elements + tag['player'] = el['player'] = this; + // Default state of video is paused + this.addClass('vjs-paused'); + + // Make box use width/height of tag, or rely on default implementation + // Enforce with CSS since width/height attrs don't work on divs + this.width(this.options_['width'], true); // (true) Skip resize listener on load + this.height(this.options_['height'], true); + + // Wrap video tag in div (el/box) container + if (tag.parentNode) { + tag.parentNode.insertBefore(el, tag); + } + vjs.insertFirst(tag, el); // Breaks iPhone, fixed in HTML5 setup. + + return el; +}; + +// /* Media Technology (tech) +// ================================================================================ */ +// Load/Create an instance of playback technlogy including element and API methods +// And append playback element in player div. +vjs.Player.prototype.loadTech = function(techName, source){ + + // Pause and remove current playback technology + if (this.tech) { + this.unloadTech(); + + // If the first time loading, HTML5 tag will exist but won't be initialized + // So we need to remove it if we're not loading HTML5 + } else if (techName !== 'Html5' && this.tag) { + this.el_.removeChild(this.tag); + this.tag['player'] = null; + this.tag = null; + } + + this.techName = techName; + + // Turn off API access because we're loading a new tech that might load asynchronously + this.isReady_ = false; + + var techReady = function(){ + this.player_.triggerReady(); + + // Manually track progress in cases where the browser/flash player doesn't report it. + if (!this.features['progressEvents']) { + this.player_.manualProgressOn(); + } + + // Manually track timeudpates in cases where the browser/flash player doesn't report it. + if (!this.features['timeupdateEvents']) { + this.player_.manualTimeUpdatesOn(); + } + }; + + // Grab tech-specific options from player options and add source and parent element to use. + var techOptions = vjs.obj.merge({ 'source': source, 'parentEl': this.el_ }, this.options_[techName.toLowerCase()]); + + if (source) { + if (source.src == this.cache_.src && this.cache_.currentTime > 0) { + techOptions['startTime'] = this.cache_.currentTime; + } + + this.cache_.src = source.src; + } + + // Initialize tech instance + this.tech = new window['videojs'][techName](this, techOptions); + + this.tech.ready(techReady); +}; + +vjs.Player.prototype.unloadTech = function(){ + this.isReady_ = false; + this.tech.dispose(); + + // Turn off any manual progress or timeupdate tracking + if (this.manualProgress) { this.manualProgressOff(); } + + if (this.manualTimeUpdates) { this.manualTimeUpdatesOff(); } + + this.tech = false; +}; + +// There's many issues around changing the size of a Flash (or other plugin) object. +// First is a plugin reload issue in Firefox that has been around for 11 years: https://bugzilla.mozilla.org/show_bug.cgi?id=90268 +// Then with the new fullscreen API, Mozilla and webkit browsers will reload the flash object after going to fullscreen. +// To get around this, we're unloading the tech, caching source and currentTime values, and reloading the tech once the plugin is resized. +// reloadTech: function(betweenFn){ +// vjs.log('unloadingTech') +// this.unloadTech(); +// vjs.log('unloadedTech') +// if (betweenFn) { betweenFn.call(); } +// vjs.log('LoadingTech') +// this.loadTech(this.techName, { src: this.cache_.src }) +// vjs.log('loadedTech') +// }, + +/* Fallbacks for unsupported event types +================================================================================ */ +// Manually trigger progress events based on changes to the buffered amount +// Many flash players and older HTML5 browsers don't send progress or progress-like events +vjs.Player.prototype.manualProgressOn = function(){ + this.manualProgress = true; + + // Trigger progress watching when a source begins loading + this.trackProgress(); + + // Watch for a native progress event call on the tech element + // In HTML5, some older versions don't support the progress event + // So we're assuming they don't, and turning off manual progress if they do. + // As opposed to doing user agent detection + this.tech.one('progress', function(){ + + // Update known progress support for this playback technology + this.features['progressEvents'] = true; + + // Turn off manual progress tracking + this.player_.manualProgressOff(); + }); +}; + +vjs.Player.prototype.manualProgressOff = function(){ + this.manualProgress = false; + this.stopTrackingProgress(); +}; + +vjs.Player.prototype.trackProgress = function(){ + + this.progressInterval = setInterval(vjs.bind(this, function(){ + // Don't trigger unless buffered amount is greater than last time + // log(this.cache_.bufferEnd, this.buffered().end(0), this.duration()) + /* TODO: update for multiple buffered regions */ + if (this.cache_.bufferEnd < this.buffered().end(0)) { + this.trigger('progress'); + } else if (this.bufferedPercent() == 1) { + this.stopTrackingProgress(); + this.trigger('progress'); // Last update + } + }), 500); +}; +vjs.Player.prototype.stopTrackingProgress = function(){ clearInterval(this.progressInterval); }; + +/* Time Tracking -------------------------------------------------------------- */ +vjs.Player.prototype.manualTimeUpdatesOn = function(){ + this.manualTimeUpdates = true; + + this.on('play', this.trackCurrentTime); + this.on('pause', this.stopTrackingCurrentTime); + // timeupdate is also called by .currentTime whenever current time is set + + // Watch for native timeupdate event + this.tech.one('timeupdate', function(){ + // Update known progress support for this playback technology + this.features['timeupdateEvents'] = true; + // Turn off manual progress tracking + this.player_.manualTimeUpdatesOff(); + }); +}; + +vjs.Player.prototype.manualTimeUpdatesOff = function(){ + this.manualTimeUpdates = false; + this.stopTrackingCurrentTime(); + this.off('play', this.trackCurrentTime); + this.off('pause', this.stopTrackingCurrentTime); +}; + +vjs.Player.prototype.trackCurrentTime = function(){ + if (this.currentTimeInterval) { this.stopTrackingCurrentTime(); } + this.currentTimeInterval = setInterval(vjs.bind(this, function(){ + this.trigger('timeupdate'); + }), 250); // 42 = 24 fps // 250 is what Webkit uses // FF uses 15 +}; + +// Turn off play progress tracking (when paused or dragging) +vjs.Player.prototype.stopTrackingCurrentTime = function(){ clearInterval(this.currentTimeInterval); }; + +// /* Player event handlers (how the player reacts to certain events) +// ================================================================================ */ +vjs.Player.prototype.onEnded = function(){ + if (this.options_['loop']) { + this.currentTime(0); + this.play(); + } +}; + +vjs.Player.prototype.onPlay = function(){ + vjs.removeClass(this.el_, 'vjs-paused'); + vjs.addClass(this.el_, 'vjs-playing'); +}; + +vjs.Player.prototype.onFirstPlay = function(){ + //If the first starttime attribute is specified + //then we will start at the given offset in seconds + if(this.options_['starttime']){ + this.currentTime(this.options_['starttime']); + } + + this.addClass('vjs-has-started'); +}; + +vjs.Player.prototype.onPause = function(){ + vjs.removeClass(this.el_, 'vjs-playing'); + vjs.addClass(this.el_, 'vjs-paused'); +}; + +vjs.Player.prototype.onProgress = function(){ + // Add custom event for when source is finished downloading. + if (this.bufferedPercent() == 1) { + this.trigger('loadedalldata'); + } +}; + +// Update duration with durationchange event +// Allows for cacheing value instead of asking player each time. +vjs.Player.prototype.onDurationChange = function(){ + this.duration(this.techGet('duration')); +}; + +vjs.Player.prototype.onError = function(e) { + vjs.log('Video Error', e); +}; + +vjs.Player.prototype.onFullscreenChange = function() { + if (this.isFullScreen) { + this.addClass('vjs-fullscreen'); + } else { + this.removeClass('vjs-fullscreen'); + } +}; + +// /* Player API +// ================================================================================ */ + +/** + * Object for cached values. + * @private + */ +vjs.Player.prototype.cache_; + +vjs.Player.prototype.getCache = function(){ + return this.cache_; +}; + +// Pass values to the playback tech +vjs.Player.prototype.techCall = function(method, arg){ + // If it's not ready yet, call method when it is + if (this.tech && !this.tech.isReady_) { + this.tech.ready(function(){ + this[method](arg); + }); + + // Otherwise call method now + } else { + try { + this.tech[method](arg); + } catch(e) { + vjs.log(e); + throw e; + } + } +}; + +// Get calls can't wait for the tech, and sometimes don't need to. +vjs.Player.prototype.techGet = function(method){ + + if (this.tech && this.tech.isReady_) { + + // Flash likes to die and reload when you hide or reposition it. + // In these cases the object methods go away and we get errors. + // When that happens we'll catch the errors and inform tech that it's not ready any more. + try { + return this.tech[method](); + } catch(e) { + // When building additional tech libs, an expected method may not be defined yet + if (this.tech[method] === undefined) { + vjs.log('Video.js: ' + method + ' method not defined for '+this.techName+' playback technology.', e); + } else { + // When a method isn't available on the object it throws a TypeError + if (e.name == 'TypeError') { + vjs.log('Video.js: ' + method + ' unavailable on '+this.techName+' playback technology element.', e); + this.tech.isReady_ = false; + } else { + vjs.log(e); + } + } + throw e; + } + } + + return; +}; + +/** + * Start media playback + * http://dev.w3.org/html5/spec/video.html#dom-media-play + * We're triggering the 'play' event here instead of relying on the + * media element to allow using event.preventDefault() to stop + * play from happening if desired. Usecase: preroll ads. + */ +vjs.Player.prototype.play = function(){ + this.techCall('play'); + return this; +}; + +// http://dev.w3.org/html5/spec/video.html#dom-media-pause +vjs.Player.prototype.pause = function(){ + this.techCall('pause'); + return this; +}; + +// http://dev.w3.org/html5/spec/video.html#dom-media-paused +// The initial state of paused should be true (in Safari it's actually false) +vjs.Player.prototype.paused = function(){ + return (this.techGet('paused') === false) ? false : true; +}; + +// http://dev.w3.org/html5/spec/video.html#dom-media-currenttime +vjs.Player.prototype.currentTime = function(seconds){ + if (seconds !== undefined) { + + // Cache the last set value for smoother scrubbing. + this.cache_.lastSetCurrentTime = seconds; + + this.techCall('setCurrentTime', seconds); + + // Improve the accuracy of manual timeupdates + if (this.manualTimeUpdates) { this.trigger('timeupdate'); } + + return this; + } + + // Cache last currentTime and return + // Default to 0 seconds + return this.cache_.currentTime = (this.techGet('currentTime') || 0); +}; + +// http://dev.w3.org/html5/spec/video.html#dom-media-duration +// Duration should return NaN if not available. ParseFloat will turn false-ish values to NaN. +vjs.Player.prototype.duration = function(seconds){ + if (seconds !== undefined) { + + // Cache the last set value for optimiized scrubbing (esp. Flash) + this.cache_.duration = parseFloat(seconds); + + return this; + } + + return this.cache_.duration; +}; + +// Calculates how much time is left. Not in spec, but useful. +vjs.Player.prototype.remainingTime = function(){ + return this.duration() - this.currentTime(); +}; + +// http://dev.w3.org/html5/spec/video.html#dom-media-buffered +// Buffered returns a timerange object. +// Kind of like an array of portions of the video that have been downloaded. +// So far no browsers return more than one range (portion) +vjs.Player.prototype.buffered = function(){ + var buffered = this.techGet('buffered'), + start = 0, + buflast = buffered.length - 1, + // Default end to 0 and store in values + end = this.cache_.bufferEnd = this.cache_.bufferEnd || 0; + + if (buffered && buflast >= 0 && buffered.end(buflast) !== end) { + end = buffered.end(buflast); + // Storing values allows them be overridden by setBufferedFromProgress + this.cache_.bufferEnd = end; + } + + return vjs.createTimeRange(start, end); +}; + +// Calculates amount of buffer is full. Not in spec but useful. +vjs.Player.prototype.bufferedPercent = function(){ + return (this.duration()) ? this.buffered().end(0) / this.duration() : 0; +}; + +// http://dev.w3.org/html5/spec/video.html#dom-media-volume +vjs.Player.prototype.volume = function(percentAsDecimal){ + var vol; + + if (percentAsDecimal !== undefined) { + vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal))); // Force value to between 0 and 1 + this.cache_.volume = vol; + this.techCall('setVolume', vol); + vjs.setLocalStorage('volume', vol); + return this; + } + + // Default to 1 when returning current volume. + vol = parseFloat(this.techGet('volume')); + return (isNaN(vol)) ? 1 : vol; +}; + +// http://dev.w3.org/html5/spec/video.html#attr-media-muted +vjs.Player.prototype.muted = function(muted){ + if (muted !== undefined) { + this.techCall('setMuted', muted); + return this; + } + return this.techGet('muted') || false; // Default to false +}; + +// Check if current tech can support native fullscreen (e.g. with built in controls lik iOS, so not our flash swf) +vjs.Player.prototype.supportsFullScreen = function(){ return this.techGet('supportsFullScreen') || false; }; + +// Turn on fullscreen (or window) mode +vjs.Player.prototype.requestFullScreen = function(){ + var requestFullScreen = vjs.support.requestFullScreen; + this.isFullScreen = true; + + if (requestFullScreen) { + // the browser supports going fullscreen at the element level so we can + // take the controls fullscreen as well as the video + + // Trigger fullscreenchange event after change + // We have to specifically add this each time, and remove + // when cancelling fullscreen. Otherwise if there's multiple + // players on a page, they would all be reacting to the same fullscreen + // events + vjs.on(document, requestFullScreen.eventName, vjs.bind(this, function(e){ + this.isFullScreen = document[requestFullScreen.isFullScreen]; + + // If cancelling fullscreen, remove event listener. + if (this.isFullScreen === false) { + vjs.off(document, requestFullScreen.eventName, arguments.callee); + } + + this.trigger('fullscreenchange'); + })); + + this.el_[requestFullScreen.requestFn](); + + } else if (this.tech.supportsFullScreen()) { + // we can't take the video.js controls fullscreen but we can go fullscreen + // with native controls + this.techCall('enterFullScreen'); + } else { + // fullscreen isn't supported so we'll just stretch the video element to + // fill the viewport + this.enterFullWindow(); + this.trigger('fullscreenchange'); + } + + return this; +}; + +vjs.Player.prototype.cancelFullScreen = function(){ + var requestFullScreen = vjs.support.requestFullScreen; + this.isFullScreen = false; + + // Check for browser element fullscreen support + if (requestFullScreen) { + document[requestFullScreen.cancelFn](); + } else if (this.tech.supportsFullScreen()) { + this.techCall('exitFullScreen'); + } else { + this.exitFullWindow(); + this.trigger('fullscreenchange'); + } + + return this; +}; + +// When fullscreen isn't supported we can stretch the video container to as wide as the browser will let us. +vjs.Player.prototype.enterFullWindow = function(){ + this.isFullWindow = true; + + // Storing original doc overflow value to return to when fullscreen is off + this.docOrigOverflow = document.documentElement.style.overflow; + + // Add listener for esc key to exit fullscreen + vjs.on(document, 'keydown', vjs.bind(this, this.fullWindowOnEscKey)); + + // Hide any scroll bars + document.documentElement.style.overflow = 'hidden'; + + // Apply fullscreen styles + vjs.addClass(document.body, 'vjs-full-window'); + + this.trigger('enterFullWindow'); +}; +vjs.Player.prototype.fullWindowOnEscKey = function(event){ + if (event.keyCode === 27) { + if (this.isFullScreen === true) { + this.cancelFullScreen(); + } else { + this.exitFullWindow(); + } + } +}; + +vjs.Player.prototype.exitFullWindow = function(){ + this.isFullWindow = false; + vjs.off(document, 'keydown', this.fullWindowOnEscKey); + + // Unhide scroll bars. + document.documentElement.style.overflow = this.docOrigOverflow; + + // Remove fullscreen styles + vjs.removeClass(document.body, 'vjs-full-window'); + + // Resize the box, controller, and poster to original sizes + // this.positionAll(); + this.trigger('exitFullWindow'); +}; + +vjs.Player.prototype.selectSource = function(sources){ + + // Loop through each playback technology in the options order + for (var i=0,j=this.options_['techOrder'];i<j.length;i++) { + var techName = vjs.capitalize(j[i]), + tech = window['videojs'][techName]; + + // Check if the browser supports this technology + if (tech.isSupported()) { + // Loop through each source object + for (var a=0,b=sources;a<b.length;a++) { + var source = b[a]; + + // Check if source can be played with this technology + if (tech['canPlaySource'](source)) { + return { source: source, tech: techName }; + } + } + } + } + + return false; +}; + +// src is a pretty powerful function +// If you pass it an array of source objects, it will find the best source to play and use that object.src +// If the new source requires a new playback technology, it will switch to that. +// If you pass it an object, it will set the source to object.src +// If you pass it anything else (url string) it will set the video source to that +vjs.Player.prototype.src = function(source){ + // Case: Array of source objects to choose from and pick the best to play + if (source instanceof Array) { + + var sourceTech = this.selectSource(source), + techName; + + if (sourceTech) { + source = sourceTech.source; + techName = sourceTech.tech; + + // If this technology is already loaded, set source + if (techName == this.techName) { + this.src(source); // Passing the source object + // Otherwise load this technology with chosen source + } else { + this.loadTech(techName, source); + } + } else { + this.el_.appendChild(vjs.createEl('p', { + innerHTML: this.options()['notSupportedMessage'] + })); + } + + // Case: Source object { src: '', type: '' ... } + } else if (source instanceof Object) { + + if (window['videojs'][this.techName]['canPlaySource'](source)) { + this.src(source.src); + } else { + // Send through tech loop to check for a compatible technology. + this.src([source]); + } + + // Case: URL String (http://myvideo...) + } else { + // Cache for getting last set source + this.cache_.src = source; + + if (!this.isReady_) { + this.ready(function(){ + this.src(source); + }); + } else { + this.techCall('src', source); + if (this.options_['preload'] == 'auto') { + this.load(); + } + if (this.options_['autoplay']) { + this.play(); + } + } + } + return this; +}; + +// Begin loading the src data +// http://dev.w3.org/html5/spec/video.html#dom-media-load +vjs.Player.prototype.load = function(){ + this.techCall('load'); + return this; +}; + +// http://dev.w3.org/html5/spec/video.html#dom-media-currentsrc +vjs.Player.prototype.currentSrc = function(){ + return this.techGet('currentSrc') || this.cache_.src || ''; +}; + +// Attributes/Options +vjs.Player.prototype.preload = function(value){ + if (value !== undefined) { + this.techCall('setPreload', value); + this.options_['preload'] = value; + return this; + } + return this.techGet('preload'); +}; +vjs.Player.prototype.autoplay = function(value){ + if (value !== undefined) { + this.techCall('setAutoplay', value); + this.options_['autoplay'] = value; + return this; + } + return this.techGet('autoplay', value); +}; +vjs.Player.prototype.loop = function(value){ + if (value !== undefined) { + this.techCall('setLoop', value); + this.options_['loop'] = value; + return this; + } + return this.techGet('loop'); +}; + +/** + * The url of the poster image source. + * @type {String} + * @private + */ +vjs.Player.prototype.poster_; + +/** + * Get or set the poster image source url. + * @param {String} src Poster image source URL + * @return {String} Poster image source URL or null + */ +vjs.Player.prototype.poster = function(src){ + if (src !== undefined) { + this.poster_ = src; + } + return this.poster_; +}; + +/** + * Whether or not the controls are showing + * @type {Boolean} + * @private + */ +vjs.Player.prototype.controls_; + +/** + * Get or set whether or not the controls are showing. + * @param {Boolean} controls Set controls to showing or not + * @return {Boolean} Controls are showing + */ +vjs.Player.prototype.controls = function(bool){ + if (bool !== undefined) { + bool = !!bool; // force boolean + // Don't trigger a change event unless it actually changed + if (this.controls_ !== bool) { + this.controls_ = bool; + if (bool) { + this.removeClass('vjs-controls-disabled'); + this.addClass('vjs-controls-enabled'); + this.trigger('controlsenabled'); + } else { + this.removeClass('vjs-controls-enabled'); + this.addClass('vjs-controls-disabled'); + this.trigger('controlsdisabled'); + } + } + return this; + } + return this.controls_; +}; + +vjs.Player.prototype.usingNativeControls_; + +/** + * Toggle native controls on/off. Native controls are the controls built into + * devices (e.g. default iPhone controls), Flash, or other techs + * (e.g. Vimeo Controls) + * + * **This should only be set by the current tech, because only the tech knows + * if it can support native controls** + * + * @param {Boolean} bool True signals that native controls are on + * @return {vjs.Player} Returns the player + */ +vjs.Player.prototype.usingNativeControls = function(bool){ + if (bool !== undefined) { + bool = !!bool; // force boolean + // Don't trigger a change event unless it actually changed + if (this.usingNativeControls_ !== bool) { + this.usingNativeControls_ = bool; + if (bool) { + this.addClass('vjs-using-native-controls'); + this.trigger('usingnativecontrols'); + } else { + this.removeClass('vjs-using-native-controls'); + this.trigger('usingcustomcontrols'); + } + } + return this; + } + return this.usingNativeControls_; +}; + +vjs.Player.prototype.error = function(){ return this.techGet('error'); }; +vjs.Player.prototype.ended = function(){ return this.techGet('ended'); }; +vjs.Player.prototype.seeking = function(){ return this.techGet('seeking'); }; + +// When the player is first initialized, trigger activity so components +// like the control bar show themselves if needed +vjs.Player.prototype.userActivity_ = true; +vjs.Player.prototype.reportUserActivity = function(event){ + this.userActivity_ = true; +}; + +vjs.Player.prototype.userActive_ = true; +vjs.Player.prototype.userActive = function(bool){ + if (bool !== undefined) { + bool = !!bool; + if (bool !== this.userActive_) { + this.userActive_ = bool; + if (bool) { + // If the user was inactive and is now active we want to reset the + // inactivity timer + this.userActivity_ = true; + this.removeClass('vjs-user-inactive'); + this.addClass('vjs-user-active'); + this.trigger('useractive'); + } else { + // We're switching the state to inactive manually, so erase any other + // activity + this.userActivity_ = false; + + // Chrome/Safari/IE have bugs where when you change the cursor it can + // trigger a mousemove event. This causes an issue when you're hiding + // the cursor when the user is inactive, and a mousemove signals user + // activity. Making it impossible to go into inactive mode. Specifically + // this happens in fullscreen when we really need to hide the cursor. + // + // When this gets resolved in ALL browsers it can be removed + // https://code.google.com/p/chromium/issues/detail?id=103041 + this.tech.one('mousemove', function(e){ + e.stopPropagation(); + e.preventDefault(); + }); + this.removeClass('vjs-user-active'); + this.addClass('vjs-user-inactive'); + this.trigger('userinactive'); + } + } + return this; + } + return this.userActive_; +}; + +vjs.Player.prototype.listenForUserActivity = function(){ + var onMouseActivity, onMouseDown, mouseInProgress, onMouseUp, + activityCheck, inactivityTimeout; + + onMouseActivity = this.reportUserActivity; + + onMouseDown = function() { + onMouseActivity(); + // For as long as the they are touching the device or have their mouse down, + // we consider them active even if they're not moving their finger or mouse. + // So we want to continue to update that they are active + clearInterval(mouseInProgress); + // Setting userActivity=true now and setting the interval to the same time + // as the activityCheck interval (250) should ensure we never miss the + // next activityCheck + mouseInProgress = setInterval(vjs.bind(this, onMouseActivity), 250); + }; + + onMouseUp = function(event) { + onMouseActivity(); + // Stop the interval that maintains activity if the mouse/touch is down + clearInterval(mouseInProgress); + }; + + // Any mouse movement will be considered user activity + this.on('mousedown', onMouseDown); + this.on('mousemove', onMouseActivity); + this.on('mouseup', onMouseUp); + + // Listen for keyboard navigation + // Shouldn't need to use inProgress interval because of key repeat + this.on('keydown', onMouseActivity); + this.on('keyup', onMouseActivity); + + // Consider any touch events that bubble up to be activity + // Certain touches on the tech will be blocked from bubbling because they + // toggle controls + this.on('touchstart', onMouseDown); + this.on('touchmove', onMouseActivity); + this.on('touchend', onMouseUp); + this.on('touchcancel', onMouseUp); + + // Run an interval every 250 milliseconds instead of stuffing everything into + // the mousemove/touchmove function itself, to prevent performance degradation. + // `this.reportUserActivity` simply sets this.userActivity_ to true, which + // then gets picked up by this loop + // http://ejohn.org/blog/learning-from-twitter/ + activityCheck = setInterval(vjs.bind(this, function() { + // Check to see if mouse/touch activity has happened + if (this.userActivity_) { + // Reset the activity tracker + this.userActivity_ = false; + + // If the user state was inactive, set the state to active + this.userActive(true); + + // Clear any existing inactivity timeout to start the timer over + clearTimeout(inactivityTimeout); + + // In X seconds, if no more activity has occurred the user will be + // considered inactive + inactivityTimeout = setTimeout(vjs.bind(this, function() { + // Protect against the case where the inactivityTimeout can trigger just + // before the next user activity is picked up by the activityCheck loop + // causing a flicker + if (!this.userActivity_) { + this.userActive(false); + } + }), 2000); + } + }), 250); + + // Clean up the intervals when we kill the player + this.on('dispose', function(){ + clearInterval(activityCheck); + clearTimeout(inactivityTimeout); + }); +}; + +// Methods to add support for +// networkState: function(){ return this.techCall('networkState'); }, +// readyState: function(){ return this.techCall('readyState'); }, +// seeking: function(){ return this.techCall('seeking'); }, +// initialTime: function(){ return this.techCall('initialTime'); }, +// startOffsetTime: function(){ return this.techCall('startOffsetTime'); }, +// played: function(){ return this.techCall('played'); }, +// seekable: function(){ return this.techCall('seekable'); }, +// videoTracks: function(){ return this.techCall('videoTracks'); }, +// audioTracks: function(){ return this.techCall('audioTracks'); }, +// videoWidth: function(){ return this.techCall('videoWidth'); }, +// videoHeight: function(){ return this.techCall('videoHeight'); }, +// defaultPlaybackRate: function(){ return this.techCall('defaultPlaybackRate'); }, +// playbackRate: function(){ return this.techCall('playbackRate'); }, +// mediaGroup: function(){ return this.techCall('mediaGroup'); }, +// controller: function(){ return this.techCall('controller'); }, +// defaultMuted: function(){ return this.techCall('defaultMuted'); } + +// TODO +// currentSrcList: the array of sources including other formats and bitrates +// playList: array of source lists in order of playback + +// RequestFullscreen API +(function(){ + var prefix, requestFS, div; + + div = document.createElement('div'); + + requestFS = {}; + + // Current W3C Spec + // http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#api + // Mozilla Draft: https://wiki.mozilla.org/Gecko:FullScreenAPI#fullscreenchange_event + // New: https://dvcs.w3.org/hg/fullscreen/raw-file/529a67b8d9f3/Overview.html + if (div.cancelFullscreen !== undefined) { + requestFS.requestFn = 'requestFullscreen'; + requestFS.cancelFn = 'exitFullscreen'; + requestFS.eventName = 'fullscreenchange'; + requestFS.isFullScreen = 'fullScreen'; + + // Webkit (Chrome/Safari) and Mozilla (Firefox) have working implementations + // that use prefixes and vary slightly from the new W3C spec. Specifically, + // using 'exit' instead of 'cancel', and lowercasing the 'S' in Fullscreen. + // Other browsers don't have any hints of which version they might follow yet, + // so not going to try to predict by looping through all prefixes. + } else { + + if (document.mozCancelFullScreen) { + prefix = 'moz'; + requestFS.isFullScreen = prefix + 'FullScreen'; + } else { + prefix = 'webkit'; + requestFS.isFullScreen = prefix + 'IsFullScreen'; + } + + if (div[prefix + 'RequestFullScreen']) { + requestFS.requestFn = prefix + 'RequestFullScreen'; + requestFS.cancelFn = prefix + 'CancelFullScreen'; + } + requestFS.eventName = prefix + 'fullscreenchange'; + } + + if (document[requestFS.cancelFn]) { + vjs.support.requestFullScreen = requestFS; + } + +})(); + + +/** + * Container of main controls + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.ControlBar = vjs.Component.extend(); + +vjs.ControlBar.prototype.options_ = { + loadEvent: 'play', + children: { + 'playToggle': {}, + 'currentTimeDisplay': {}, + 'timeDivider': {}, + 'durationDisplay': {}, + 'remainingTimeDisplay': {}, + 'progressControl': {}, + 'fullscreenToggle': {}, + 'volumeControl': {}, + 'muteToggle': {} + // 'volumeMenuButton': {} + } +}; + +vjs.ControlBar.prototype.createEl = function(){ + return vjs.createEl('div', { + className: 'vjs-control-bar' + }); +}; +/** + * Button to toggle between play and pause + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.PlayToggle = vjs.Button.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Button.call(this, player, options); + + player.on('play', vjs.bind(this, this.onPlay)); + player.on('pause', vjs.bind(this, this.onPause)); + } +}); + +vjs.PlayToggle.prototype.buttonText = 'Play'; + +vjs.PlayToggle.prototype.buildCSSClass = function(){ + return 'vjs-play-control ' + vjs.Button.prototype.buildCSSClass.call(this); +}; + + // OnClick - Toggle between play and pause +vjs.PlayToggle.prototype.onClick = function(){ + if (this.player_.paused()) { + this.player_.play(); + } else { + this.player_.pause(); + } +}; + + // OnPlay - Add the vjs-playing class to the element so it can change appearance +vjs.PlayToggle.prototype.onPlay = function(){ + vjs.removeClass(this.el_, 'vjs-paused'); + vjs.addClass(this.el_, 'vjs-playing'); + this.el_.children[0].children[0].innerHTML = 'Pause'; // change the button text to "Pause" +}; + + // OnPause - Add the vjs-paused class to the element so it can change appearance +vjs.PlayToggle.prototype.onPause = function(){ + vjs.removeClass(this.el_, 'vjs-playing'); + vjs.addClass(this.el_, 'vjs-paused'); + this.el_.children[0].children[0].innerHTML = 'Play'; // change the button text to "Play" +};/** + * Displays the current time + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.CurrentTimeDisplay = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + + player.on('timeupdate', vjs.bind(this, this.updateContent)); + } +}); + +vjs.CurrentTimeDisplay.prototype.createEl = function(){ + var el = vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-current-time vjs-time-controls vjs-control' + }); + + this.content = vjs.createEl('div', { + className: 'vjs-current-time-display', + innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00', // label the current time for screen reader users + 'aria-live': 'off' // tell screen readers not to automatically read the time as it changes + }); + + el.appendChild(vjs.createEl('div').appendChild(this.content)); + return el; +}; + +vjs.CurrentTimeDisplay.prototype.updateContent = function(){ + // Allows for smooth scrubbing, when player can't keep up. + var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime(); + this.content.innerHTML = '<span class="vjs-control-text">Current Time </span>' + vjs.formatTime(time, this.player_.duration()); +}; + +/** + * Displays the duration + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.DurationDisplay = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + + player.on('timeupdate', vjs.bind(this, this.updateContent)); // this might need to be changes to 'durationchange' instead of 'timeupdate' eventually, however the durationchange event fires before this.player_.duration() is set, so the value cannot be written out using this method. Once the order of durationchange and this.player_.duration() being set is figured out, this can be updated. + } +}); + +vjs.DurationDisplay.prototype.createEl = function(){ + var el = vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-duration vjs-time-controls vjs-control' + }); + + this.content = vjs.createEl('div', { + className: 'vjs-duration-display', + innerHTML: '<span class="vjs-control-text">Duration Time </span>' + '0:00', // label the duration time for screen reader users + 'aria-live': 'off' // tell screen readers not to automatically read the time as it changes + }); + + el.appendChild(vjs.createEl('div').appendChild(this.content)); + return el; +}; + +vjs.DurationDisplay.prototype.updateContent = function(){ + var duration = this.player_.duration(); + if (duration) { + this.content.innerHTML = '<span class="vjs-control-text">Duration Time </span>' + vjs.formatTime(duration); // label the duration time for screen reader users + } +}; + +/** + * Time Separator (Not used in main skin, but still available, and could be used as a 'spare element') + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.TimeDivider = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + } +}); + +vjs.TimeDivider.prototype.createEl = function(){ + return vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-time-divider', + innerHTML: '<div><span>/</span></div>' + }); +}; + +/** + * Displays the time left in the video + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.RemainingTimeDisplay = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + + player.on('timeupdate', vjs.bind(this, this.updateContent)); + } +}); + +vjs.RemainingTimeDisplay.prototype.createEl = function(){ + var el = vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-remaining-time vjs-time-controls vjs-control' + }); + + this.content = vjs.createEl('div', { + className: 'vjs-remaining-time-display', + innerHTML: '<span class="vjs-control-text">Remaining Time </span>' + '-0:00', // label the remaining time for screen reader users + 'aria-live': 'off' // tell screen readers not to automatically read the time as it changes + }); + + el.appendChild(vjs.createEl('div').appendChild(this.content)); + return el; +}; + +vjs.RemainingTimeDisplay.prototype.updateContent = function(){ + if (this.player_.duration()) { + this.content.innerHTML = '<span class="vjs-control-text">Remaining Time </span>' + '-'+ vjs.formatTime(this.player_.remainingTime()); + } + + // Allows for smooth scrubbing, when player can't keep up. + // var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime(); + // this.content.innerHTML = vjs.formatTime(time, this.player_.duration()); +}; +/** + * Toggle fullscreen video + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.FullscreenToggle = vjs.Button.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Button.call(this, player, options); + } +}); + +vjs.FullscreenToggle.prototype.buttonText = 'Fullscreen'; + +vjs.FullscreenToggle.prototype.buildCSSClass = function(){ + return 'vjs-fullscreen-control ' + vjs.Button.prototype.buildCSSClass.call(this); +}; + +vjs.FullscreenToggle.prototype.onClick = function(){ + if (!this.player_.isFullScreen) { + this.player_.requestFullScreen(); + this.el_.children[0].children[0].innerHTML = 'Non-Fullscreen'; // change the button text to "Non-Fullscreen" + } else { + this.player_.cancelFullScreen(); + this.el_.children[0].children[0].innerHTML = 'Fullscreen'; // change the button to "Fullscreen" + } +};/** + * Seek, Load Progress, and Play Progress + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.ProgressControl = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + } +}); + +vjs.ProgressControl.prototype.options_ = { + children: { + 'seekBar': {} + } +}; + +vjs.ProgressControl.prototype.createEl = function(){ + return vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-progress-control vjs-control' + }); +}; + +/** + * Seek Bar and holder for the progress bars + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.SeekBar = vjs.Slider.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Slider.call(this, player, options); + player.on('timeupdate', vjs.bind(this, this.updateARIAAttributes)); + player.ready(vjs.bind(this, this.updateARIAAttributes)); + } +}); + +vjs.SeekBar.prototype.options_ = { + children: { + 'loadProgressBar': {}, + 'playProgressBar': {}, + 'seekHandle': {} + }, + 'barName': 'playProgressBar', + 'handleName': 'seekHandle' +}; + +vjs.SeekBar.prototype.playerEvent = 'timeupdate'; + +vjs.SeekBar.prototype.createEl = function(){ + return vjs.Slider.prototype.createEl.call(this, 'div', { + className: 'vjs-progress-holder', + 'aria-label': 'video progress bar' + }); +}; + +vjs.SeekBar.prototype.updateARIAAttributes = function(){ + // Allows for smooth scrubbing, when player can't keep up. + var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime(); + this.el_.setAttribute('aria-valuenow',vjs.round(this.getPercent()*100, 2)); // machine readable value of progress bar (percentage complete) + this.el_.setAttribute('aria-valuetext',vjs.formatTime(time, this.player_.duration())); // human readable value of progress bar (time complete) +}; + +vjs.SeekBar.prototype.getPercent = function(){ + var currentTime; + // Flash RTMP provider will not report the correct time + // immediately after a seek. This isn't noticeable if you're + // seeking while the video is playing, but it is if you seek + // while the video is paused. + if (this.player_.techName === 'Flash' && this.player_.seeking()) { + var cache = this.player_.getCache(); + if (cache.lastSetCurrentTime) { + currentTime = cache.lastSetCurrentTime; + } + else { + currentTime = this.player_.currentTime(); + } + } + else { + currentTime = this.player_.currentTime(); + } + + return currentTime / this.player_.duration(); +}; + +vjs.SeekBar.prototype.onMouseDown = function(event){ + vjs.Slider.prototype.onMouseDown.call(this, event); + + this.player_.scrubbing = true; + + this.videoWasPlaying = !this.player_.paused(); + this.player_.pause(); +}; + +vjs.SeekBar.prototype.onMouseMove = function(event){ + var newTime = this.calculateDistance(event) * this.player_.duration(); + + // Don't let video end while scrubbing. + if (newTime == this.player_.duration()) { newTime = newTime - 0.1; } + + // Set new time (tell player to seek to new time) + this.player_.currentTime(newTime); +}; + +vjs.SeekBar.prototype.onMouseUp = function(event){ + vjs.Slider.prototype.onMouseUp.call(this, event); + + this.player_.scrubbing = false; + if (this.videoWasPlaying) { + this.player_.play(); + } +}; + +vjs.SeekBar.prototype.stepForward = function(){ + this.player_.currentTime(this.player_.currentTime() + 5); // more quickly fast forward for keyboard-only users +}; + +vjs.SeekBar.prototype.stepBack = function(){ + this.player_.currentTime(this.player_.currentTime() - 5); // more quickly rewind for keyboard-only users +}; + + +/** + * Shows load progres + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.LoadProgressBar = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + player.on('progress', vjs.bind(this, this.update)); + } +}); + +vjs.LoadProgressBar.prototype.createEl = function(){ + return vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-load-progress', + innerHTML: '<span class="vjs-control-text">Loaded: 0%</span>' + }); +}; + +vjs.LoadProgressBar.prototype.update = function(){ + if (this.el_.style) { this.el_.style.width = vjs.round(this.player_.bufferedPercent() * 100, 2) + '%'; } +}; + + +/** + * Shows play progress + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.PlayProgressBar = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + } +}); + +vjs.PlayProgressBar.prototype.createEl = function(){ + return vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-play-progress', + innerHTML: '<span class="vjs-control-text">Progress: 0%</span>' + }); +}; + +/** + * SeekBar component includes play progress bar, and seek handle + * Needed so it can determine seek position based on handle position/size + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.SeekHandle = vjs.SliderHandle.extend(); + +/** @inheritDoc */ +vjs.SeekHandle.prototype.defaultValue = '00:00'; + +/** @inheritDoc */ +vjs.SeekHandle.prototype.createEl = function(){ + return vjs.SliderHandle.prototype.createEl.call(this, 'div', { + className: 'vjs-seek-handle' + }); +};/** + * Control the volume + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.VolumeControl = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + + // hide volume controls when they're not supported by the current tech + if (player.tech && player.tech.features && player.tech.features['volumeControl'] === false) { + this.addClass('vjs-hidden'); + } + player.on('loadstart', vjs.bind(this, function(){ + if (player.tech.features && player.tech.features['volumeControl'] === false) { + this.addClass('vjs-hidden'); + } else { + this.removeClass('vjs-hidden'); + } + })); + } +}); + +vjs.VolumeControl.prototype.options_ = { + children: { + 'volumeBar': {} + } +}; + +vjs.VolumeControl.prototype.createEl = function(){ + return vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-volume-control vjs-control' + }); +}; + +/** + * Contains volume level + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.VolumeBar = vjs.Slider.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Slider.call(this, player, options); + player.on('volumechange', vjs.bind(this, this.updateARIAAttributes)); + player.ready(vjs.bind(this, this.updateARIAAttributes)); + setTimeout(vjs.bind(this, this.update), 0); // update when elements is in DOM + } +}); + +vjs.VolumeBar.prototype.updateARIAAttributes = function(){ + // Current value of volume bar as a percentage + this.el_.setAttribute('aria-valuenow',vjs.round(this.player_.volume()*100, 2)); + this.el_.setAttribute('aria-valuetext',vjs.round(this.player_.volume()*100, 2)+'%'); +}; + +vjs.VolumeBar.prototype.options_ = { + children: { + 'volumeLevel': {}, + 'volumeHandle': {} + }, + 'barName': 'volumeLevel', + 'handleName': 'volumeHandle' +}; + +vjs.VolumeBar.prototype.playerEvent = 'volumechange'; + +vjs.VolumeBar.prototype.createEl = function(){ + return vjs.Slider.prototype.createEl.call(this, 'div', { + className: 'vjs-volume-bar', + 'aria-label': 'volume level' + }); +}; + +vjs.VolumeBar.prototype.onMouseMove = function(event) { + this.player_.volume(this.calculateDistance(event)); +}; + +vjs.VolumeBar.prototype.getPercent = function(){ + if (this.player_.muted()) { + return 0; + } else { + return this.player_.volume(); + } +}; + +vjs.VolumeBar.prototype.stepForward = function(){ + this.player_.volume(this.player_.volume() + 0.1); +}; + +vjs.VolumeBar.prototype.stepBack = function(){ + this.player_.volume(this.player_.volume() - 0.1); +}; + +/** + * Shows volume level + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.VolumeLevel = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + } +}); + +vjs.VolumeLevel.prototype.createEl = function(){ + return vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-volume-level', + innerHTML: '<span class="vjs-control-text"></span>' + }); +}; + +/** + * Change volume level + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ + vjs.VolumeHandle = vjs.SliderHandle.extend(); + + /** @inheritDoc */ + vjs.VolumeHandle.prototype.defaultValue = '00:00'; + + /** @inheritDoc */ + vjs.VolumeHandle.prototype.createEl = function(){ + return vjs.SliderHandle.prototype.createEl.call(this, 'div', { + className: 'vjs-volume-handle' + }); + }; +/** + * Mute the audio + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.MuteToggle = vjs.Button.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Button.call(this, player, options); + + player.on('volumechange', vjs.bind(this, this.update)); + + // hide mute toggle if the current tech doesn't support volume control + if (player.tech && player.tech.features && player.tech.features['volumeControl'] === false) { + this.addClass('vjs-hidden'); + } + player.on('loadstart', vjs.bind(this, function(){ + if (player.tech.features && player.tech.features['volumeControl'] === false) { + this.addClass('vjs-hidden'); + } else { + this.removeClass('vjs-hidden'); + } + })); + } +}); + +vjs.MuteToggle.prototype.createEl = function(){ + return vjs.Button.prototype.createEl.call(this, 'div', { + className: 'vjs-mute-control vjs-control', + innerHTML: '<div><span class="vjs-control-text">Mute</span></div>' + }); +}; + +vjs.MuteToggle.prototype.onClick = function(){ + this.player_.muted( this.player_.muted() ? false : true ); +}; + +vjs.MuteToggle.prototype.update = function(){ + var vol = this.player_.volume(), + level = 3; + + if (vol === 0 || this.player_.muted()) { + level = 0; + } else if (vol < 0.33) { + level = 1; + } else if (vol < 0.67) { + level = 2; + } + + // Don't rewrite the button text if the actual text doesn't change. + // This causes unnecessary and confusing information for screen reader users. + // This check is needed because this function gets called every time the volume level is changed. + if(this.player_.muted()){ + if(this.el_.children[0].children[0].innerHTML!='Unmute'){ + this.el_.children[0].children[0].innerHTML = 'Unmute'; // change the button text to "Unmute" + } + } else { + if(this.el_.children[0].children[0].innerHTML!='Mute'){ + this.el_.children[0].children[0].innerHTML = 'Mute'; // change the button text to "Mute" + } + } + + /* TODO improve muted icon classes */ + for (var i = 0; i < 4; i++) { + vjs.removeClass(this.el_, 'vjs-vol-'+i); + } + vjs.addClass(this.el_, 'vjs-vol-'+level); +}; +/** + * Menu button with a popup for showing the volume slider. + * @constructor + */ +vjs.VolumeMenuButton = vjs.MenuButton.extend({ + /** @constructor */ + init: function(player, options){ + vjs.MenuButton.call(this, player, options); + + // Same listeners as MuteToggle + player.on('volumechange', vjs.bind(this, this.update)); + + // hide mute toggle if the current tech doesn't support volume control + if (player.tech && player.tech.features && player.tech.features.volumeControl === false) { + this.addClass('vjs-hidden'); + } + player.on('loadstart', vjs.bind(this, function(){ + if (player.tech.features && player.tech.features.volumeControl === false) { + this.addClass('vjs-hidden'); + } else { + this.removeClass('vjs-hidden'); + } + })); + this.addClass('vjs-menu-button'); + } +}); + +vjs.VolumeMenuButton.prototype.createMenu = function(){ + var menu = new vjs.Menu(this.player_, { + contentElType: 'div' + }); + var vc = new vjs.VolumeBar(this.player_, vjs.obj.merge({vertical: true}, this.options_.volumeBar)); + menu.addChild(vc); + return menu; +}; + +vjs.VolumeMenuButton.prototype.onClick = function(){ + vjs.MuteToggle.prototype.onClick.call(this); + vjs.MenuButton.prototype.onClick.call(this); +}; + +vjs.VolumeMenuButton.prototype.createEl = function(){ + return vjs.Button.prototype.createEl.call(this, 'div', { + className: 'vjs-volume-menu-button vjs-menu-button vjs-control', + innerHTML: '<div><span class="vjs-control-text">Mute</span></div>' + }); +}; +vjs.VolumeMenuButton.prototype.update = vjs.MuteToggle.prototype.update; +/* Poster Image +================================================================================ */ +/** + * Poster image. Shows before the video plays. + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.PosterImage = vjs.Button.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Button.call(this, player, options); + + if (!player.poster() || !player.controls()) { + this.hide(); + } + + player.on('play', vjs.bind(this, this.hide)); + } +}); + +vjs.PosterImage.prototype.createEl = function(){ + var el = vjs.createEl('div', { + className: 'vjs-poster', + + // Don't want poster to be tabbable. + tabIndex: -1 + }), + poster = this.player_.poster(); + + if (poster) { + if ('backgroundSize' in el.style) { + el.style.backgroundImage = 'url("' + poster + '")'; + } else { + el.appendChild(vjs.createEl('img', { src: poster })); + } + } + + return el; +}; + +vjs.PosterImage.prototype.onClick = function(){ + // Only accept clicks when controls are enabled + if (this.player().controls()) { + this.player_.play(); + } +}; +/* Loading Spinner +================================================================================ */ +/** + * Loading spinner for waiting events + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.LoadingSpinner = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + + player.on('canplay', vjs.bind(this, this.hide)); + player.on('canplaythrough', vjs.bind(this, this.hide)); + player.on('playing', vjs.bind(this, this.hide)); + player.on('seeked', vjs.bind(this, this.hide)); + + player.on('seeking', vjs.bind(this, this.show)); + + // in some browsers seeking does not trigger the 'playing' event, + // so we also need to trap 'seeked' if we are going to set a + // 'seeking' event + player.on('seeked', vjs.bind(this, this.hide)); + + player.on('error', vjs.bind(this, this.show)); + + // Not showing spinner on stalled any more. Browsers may stall and then not trigger any events that would remove the spinner. + // Checked in Chrome 16 and Safari 5.1.2. http://help.videojs.com/discussions/problems/883-why-is-the-download-progress-showing + // player.on('stalled', vjs.bind(this, this.show)); + + player.on('waiting', vjs.bind(this, this.show)); + } +}); + +vjs.LoadingSpinner.prototype.createEl = function(){ + return vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-loading-spinner' + }); +}; +/* Big Play Button +================================================================================ */ +/** + * Initial play button. Shows before the video has played. The hiding of the + * big play button is done via CSS and player states. + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.BigPlayButton = vjs.Button.extend(); + +vjs.BigPlayButton.prototype.createEl = function(){ + return vjs.Button.prototype.createEl.call(this, 'div', { + className: 'vjs-big-play-button', + innerHTML: '<span></span>', + 'aria-label': 'play video' + }); +}; + +vjs.BigPlayButton.prototype.onClick = function(){ + this.player_.play(); +}; +/** + * @fileoverview Media Technology Controller - Base class for media playback + * technology controllers like Flash and HTML5 + */ + +/** + * Base class for media (HTML5 Video, Flash) controllers + * @param {vjs.Player|Object} player Central player instance + * @param {Object=} options Options object + * @constructor + */ +vjs.MediaTechController = vjs.Component.extend({ + /** @constructor */ + init: function(player, options, ready){ + vjs.Component.call(this, player, options, ready); + + this.initControlsListeners(); + } +}); + +/** + * Set up click and touch listeners for the playback element + * On desktops, a click on the video itself will toggle playback, + * on a mobile device a click on the video toggles controls. + * (toggling controls is done by toggling the user state between active and + * inactive) + * + * A tap can signal that a user has become active, or has become inactive + * e.g. a quick tap on an iPhone movie should reveal the controls. Another + * quick tap should hide them again (signaling the user is in an inactive + * viewing state) + * + * In addition to this, we still want the user to be considered inactive after + * a few seconds of inactivity. + * + * Note: the only part of iOS interaction we can't mimic with this setup + * is a touch and hold on the video element counting as activity in order to + * keep the controls showing, but that shouldn't be an issue. A touch and hold on + * any controls will still keep the user active + */ +vjs.MediaTechController.prototype.initControlsListeners = function(){ + var player, tech, activateControls, deactivateControls; + + tech = this; + player = this.player(); + + var activateControls = function(){ + if (player.controls() && !player.usingNativeControls()) { + tech.addControlsListeners(); + } + }; + + deactivateControls = vjs.bind(tech, tech.removeControlsListeners); + + // Set up event listeners once the tech is ready and has an element to apply + // listeners to + this.ready(activateControls); + player.on('controlsenabled', activateControls); + player.on('controlsdisabled', deactivateControls); +}; + +vjs.MediaTechController.prototype.addControlsListeners = function(){ + var preventBubble, userWasActive; + + // Some browsers (Chrome & IE) don't trigger a click on a flash swf, but do + // trigger mousedown/up. + // http://stackoverflow.com/questions/1444562/javascript-onclick-event-over-flash-object + // Any touch events are set to block the mousedown event from happening + this.on('mousedown', this.onClick); + + // We need to block touch events on the video element from bubbling up, + // otherwise they'll signal activity prematurely. The specific use case is + // when the video is playing and the controls have faded out. In this case + // only a tap (fast touch) should toggle the user active state and turn the + // controls back on. A touch and move or touch and hold should not trigger + // the controls (per iOS as an example at least) + // + // We always want to stop propagation on touchstart because touchstart + // at the player level starts the touchInProgress interval. We can still + // report activity on the other events, but won't let them bubble for + // consistency. We don't want to bubble a touchend without a touchstart. + this.on('touchstart', function(event) { + // Stop the mouse events from also happening + event.preventDefault(); + event.stopPropagation(); + // Record if the user was active now so we don't have to keep polling it + userWasActive = this.player_.userActive(); + }); + + preventBubble = function(event){ + event.stopPropagation(); + if (userWasActive) { + this.player_.reportUserActivity(); + } + }; + + // Treat all touch events the same for consistency + this.on('touchmove', preventBubble); + this.on('touchleave', preventBubble); + this.on('touchcancel', preventBubble); + this.on('touchend', preventBubble); + + // Turn on component tap events + this.emitTapEvents(); + + // The tap listener needs to come after the touchend listener because the tap + // listener cancels out any reportedUserActivity when setting userActive(false) + this.on('tap', this.onTap); +}; + +/** + * Remove the listeners used for click and tap controls. This is needed for + * toggling to controls disabled, where a tap/touch should do nothing. + */ +vjs.MediaTechController.prototype.removeControlsListeners = function(){ + // We don't want to just use `this.off()` because there might be other needed + // listeners added by techs that extend this. + this.off('tap'); + this.off('touchstart'); + this.off('touchmove'); + this.off('touchleave'); + this.off('touchcancel'); + this.off('touchend'); + this.off('click'); + this.off('mousedown'); +}; + +/** + * Handle a click on the media element. By default will play/pause the media. + */ +vjs.MediaTechController.prototype.onClick = function(event){ + // We're using mousedown to detect clicks thanks to Flash, but mousedown + // will also be triggered with right-clicks, so we need to prevent that + if (event.button !== 0) return; + + // When controls are disabled a click should not toggle playback because + // the click is considered a control + if (this.player().controls()) { + if (this.player().paused()) { + this.player().play(); + } else { + this.player().pause(); + } + } +}; + +/** + * Handle a tap on the media element. By default it will toggle the user + * activity state, which hides and shows the controls. + */ + +vjs.MediaTechController.prototype.onTap = function(){ + this.player().userActive(!this.player().userActive()); +}; + +vjs.MediaTechController.prototype.features = { + 'volumeControl': true, + + // Resizing plugins using request fullscreen reloads the plugin + 'fullscreenResize': false, + + // Optional events that we can manually mimic with timers + // currently not triggered by video-js-swf + 'progressEvents': false, + 'timeupdateEvents': false +}; + +vjs.media = {}; + +/** + * List of default API methods for any MediaTechController + * @type {String} + */ +vjs.media.ApiMethods = 'play,pause,paused,currentTime,setCurrentTime,duration,buffered,volume,setVolume,muted,setMuted,width,height,supportsFullScreen,enterFullScreen,src,load,currentSrc,preload,setPreload,autoplay,setAutoplay,loop,setLoop,error,networkState,readyState,seeking,initialTime,startOffsetTime,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks,defaultPlaybackRate,playbackRate,mediaGroup,controller,controls,defaultMuted'.split(','); +// Create placeholder methods for each that warn when a method isn't supported by the current playback technology + +function createMethod(methodName){ + return function(){ + throw new Error('The "'+methodName+'" method is not available on the playback technology\'s API'); + }; +} + +for (var i = vjs.media.ApiMethods.length - 1; i >= 0; i--) { + var methodName = vjs.media.ApiMethods[i]; + vjs.MediaTechController.prototype[vjs.media.ApiMethods[i]] = createMethod(methodName); +} +/** + * @fileoverview HTML5 Media Controller - Wrapper for HTML5 Media API + */ + +/** + * HTML5 Media Controller - Wrapper for HTML5 Media API + * @param {vjs.Player|Object} player + * @param {Object=} options + * @param {Function=} ready + * @constructor + */ +vjs.Html5 = vjs.MediaTechController.extend({ + /** @constructor */ + init: function(player, options, ready){ + // volume cannot be changed from 1 on iOS + this.features['volumeControl'] = vjs.Html5.canControlVolume(); + + // In iOS, if you move a video element in the DOM, it breaks video playback. + this.features['movingMediaElementInDOM'] = !vjs.IS_IOS; + + // HTML video is able to automatically resize when going to fullscreen + this.features['fullscreenResize'] = true; + + vjs.MediaTechController.call(this, player, options, ready); + + var source = options['source']; + + // If the element source is already set, we may have missed the loadstart event, and want to trigger it. + // We don't want to set the source again and interrupt playback. + if (source && this.el_.currentSrc == source.src) { + player.trigger('loadstart'); + + // Otherwise set the source if one was provided. + } else if (source) { + this.el_.src = source.src; + } + + // Determine if native controls should be used + // Our goal should be to get the custom controls on mobile solid everywhere + // so we can remove this all together. Right now this will block custom + // controls on touch enabled laptops like the Chrome Pixel + if (vjs.TOUCH_ENABLED && player.options()['nativeControlsForTouch'] !== false) { + this.useNativeControls(); + } + + // Chrome and Safari both have issues with autoplay. + // In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work. + // In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays) + // This fixes both issues. Need to wait for API, so it updates displays correctly + player.ready(function(){ + if (this.tag && this.options_['autoplay'] && this.paused()) { + delete this.tag['poster']; // Chrome Fix. Fixed in Chrome v16. + this.play(); + } + }); + + this.setupTriggers(); + this.triggerReady(); + } +}); + +vjs.Html5.prototype.dispose = function(){ + vjs.MediaTechController.prototype.dispose.call(this); +}; + +vjs.Html5.prototype.createEl = function(){ + var player = this.player_, + // If possible, reuse original tag for HTML5 playback technology element + el = player.tag, + newEl; + + // Check if this browser supports moving the element into the box. + // On the iPhone video will break if you move the element, + // So we have to create a brand new element. + if (!el || this.features['movingMediaElementInDOM'] === false) { + + // If the original tag is still there, remove it. + if (el) { + el['player'] = null; + player.tag = null; + player.el().removeChild(el); + el = el.cloneNode(false); + } else { + el = vjs.createEl('video', { + id:player.id() + '_html5_api', + className:'vjs-tech' + }); + } + // associate the player with the new tag + el['player'] = player; + + vjs.insertFirst(el, player.el()); + } + + // Update specific tag settings, in case they were overridden + var attrs = ['autoplay','preload','loop','muted']; + for (var i = attrs.length - 1; i >= 0; i--) { + var attr = attrs[i]; + if (player.options_[attr] !== null) { + el[attr] = player.options_[attr]; + } + } + + return el; + // jenniisawesome = true; +}; + +// Make video events trigger player events +// May seem verbose here, but makes other APIs possible. +vjs.Html5.prototype.setupTriggers = function(){ + for (var i = vjs.Html5.Events.length - 1; i >= 0; i--) { + vjs.on(this.el_, vjs.Html5.Events[i], vjs.bind(this.player_, this.eventHandler)); + } +}; +// Triggers removed using this.off when disposed + +vjs.Html5.prototype.eventHandler = function(e){ + this.trigger(e); + + // No need for media events to bubble up. + e.stopPropagation(); +}; + +vjs.Html5.prototype.useNativeControls = function(){ + var tech, player, controlsOn, controlsOff, cleanUp; + + tech = this; + player = this.player(); + + // If the player controls are enabled turn on the native controls + tech.setControls(player.controls()); + + // Update the native controls when player controls state is updated + controlsOn = function(){ + tech.setControls(true); + }; + controlsOff = function(){ + tech.setControls(false); + }; + player.on('controlsenabled', controlsOn); + player.on('controlsdisabled', controlsOff); + + // Clean up when not using native controls anymore + cleanUp = function(){ + player.off('controlsenabled', controlsOn); + player.off('controlsdisabled', controlsOff); + }; + tech.on('dispose', cleanUp); + player.on('usingcustomcontrols', cleanUp); + + // Update the state of the player to using native controls + player.usingNativeControls(true); +}; + + +vjs.Html5.prototype.play = function(){ this.el_.play(); }; +vjs.Html5.prototype.pause = function(){ this.el_.pause(); }; +vjs.Html5.prototype.paused = function(){ return this.el_.paused; }; + +vjs.Html5.prototype.currentTime = function(){ return this.el_.currentTime; }; +vjs.Html5.prototype.setCurrentTime = function(seconds){ + try { + this.el_.currentTime = seconds; + } catch(e) { + vjs.log(e, 'Video is not ready. (Video.js)'); + // this.warning(VideoJS.warnings.videoNotReady); + } +}; + +vjs.Html5.prototype.duration = function(){ return this.el_.duration || 0; }; +vjs.Html5.prototype.buffered = function(){ return this.el_.buffered; }; + +vjs.Html5.prototype.volume = function(){ return this.el_.volume; }; +vjs.Html5.prototype.setVolume = function(percentAsDecimal){ this.el_.volume = percentAsDecimal; }; +vjs.Html5.prototype.muted = function(){ return this.el_.muted; }; +vjs.Html5.prototype.setMuted = function(muted){ this.el_.muted = muted; }; + +vjs.Html5.prototype.width = function(){ return this.el_.offsetWidth; }; +vjs.Html5.prototype.height = function(){ return this.el_.offsetHeight; }; + +vjs.Html5.prototype.supportsFullScreen = function(){ + if (typeof this.el_.webkitEnterFullScreen == 'function') { + + // Seems to be broken in Chromium/Chrome && Safari in Leopard + if (/Android/.test(vjs.USER_AGENT) || !/Chrome|Mac OS X 10.5/.test(vjs.USER_AGENT)) { + return true; + } + } + return false; +}; + +vjs.Html5.prototype.enterFullScreen = function(){ + var video = this.el_; + if (video.paused && video.networkState <= video.HAVE_METADATA) { + // attempt to prime the video element for programmatic access + // this isn't necessary on the desktop but shouldn't hurt + this.el_.play(); + + // playing and pausing synchronously during the transition to fullscreen + // can get iOS ~6.1 devices into a play/pause loop + setTimeout(function(){ + video.pause(); + video.webkitEnterFullScreen(); + }, 0); + } else { + video.webkitEnterFullScreen(); + } +}; +vjs.Html5.prototype.exitFullScreen = function(){ + this.el_.webkitExitFullScreen(); +}; +vjs.Html5.prototype.src = function(src){ this.el_.src = src; }; +vjs.Html5.prototype.load = function(){ this.el_.load(); }; +vjs.Html5.prototype.currentSrc = function(){ return this.el_.currentSrc; }; + +vjs.Html5.prototype.preload = function(){ return this.el_.preload; }; +vjs.Html5.prototype.setPreload = function(val){ this.el_.preload = val; }; + +vjs.Html5.prototype.autoplay = function(){ return this.el_.autoplay; }; +vjs.Html5.prototype.setAutoplay = function(val){ this.el_.autoplay = val; }; + +vjs.Html5.prototype.controls = function(){ return this.el_.controls; } +vjs.Html5.prototype.setControls = function(val){ this.el_.controls = !!val; } + +vjs.Html5.prototype.loop = function(){ return this.el_.loop; }; +vjs.Html5.prototype.setLoop = function(val){ this.el_.loop = val; }; + +vjs.Html5.prototype.error = function(){ return this.el_.error; }; +vjs.Html5.prototype.seeking = function(){ return this.el_.seeking; }; +vjs.Html5.prototype.ended = function(){ return this.el_.ended; }; +vjs.Html5.prototype.defaultMuted = function(){ return this.el_.defaultMuted; }; + +/* HTML5 Support Testing ---------------------------------------------------- */ + +vjs.Html5.isSupported = function(){ + return !!vjs.TEST_VID.canPlayType; +}; + +vjs.Html5.canPlaySource = function(srcObj){ + // IE9 on Windows 7 without MediaPlayer throws an error here + // https://github.com/videojs/video.js/issues/519 + try { + return !!vjs.TEST_VID.canPlayType(srcObj.type); + } catch(e) { + return ''; + } + // TODO: Check Type + // If no Type, check ext + // Check Media Type +}; + +vjs.Html5.canControlVolume = function(){ + var volume = vjs.TEST_VID.volume; + vjs.TEST_VID.volume = (volume / 2) + 0.1; + return volume !== vjs.TEST_VID.volume; +}; + +// List of all HTML5 events (various uses). +vjs.Html5.Events = 'loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange'.split(','); + + +// HTML5 Feature detection and Device Fixes --------------------------------- // + + // Override Android 2.2 and less canPlayType method which is broken +if (vjs.IS_OLD_ANDROID) { + document.createElement('video').constructor.prototype.canPlayType = function(type){ + return (type && type.toLowerCase().indexOf('video/mp4') != -1) ? 'maybe' : ''; + }; +} +/** + * @fileoverview VideoJS-SWF - Custom Flash Player with HTML5-ish API + * https://github.com/zencoder/video-js-swf + * Not using setupTriggers. Using global onEvent func to distribute events + */ + +/** + * HTML5 Media Controller - Wrapper for HTML5 Media API + * @param {vjs.Player|Object} player + * @param {Object=} options + * @param {Function=} ready + * @constructor + */ +vjs.Flash = vjs.MediaTechController.extend({ + /** @constructor */ + init: function(player, options, ready){ + vjs.MediaTechController.call(this, player, options, ready); + + var source = options['source'], + + // Which element to embed in + parentEl = options['parentEl'], + + // Create a temporary element to be replaced by swf object + placeHolder = this.el_ = vjs.createEl('div', { id: player.id() + '_temp_flash' }), + + // Generate ID for swf object + objId = player.id()+'_flash_api', + + // Store player options in local var for optimization + // TODO: switch to using player methods instead of options + // e.g. player.autoplay(); + playerOptions = player.options_, + + // Merge default flashvars with ones passed in to init + flashVars = vjs.obj.merge({ + + // SWF Callback Functions + 'readyFunction': 'videojs.Flash.onReady', + 'eventProxyFunction': 'videojs.Flash.onEvent', + 'errorEventProxyFunction': 'videojs.Flash.onError', + + // Player Settings + 'autoplay': playerOptions.autoplay, + 'preload': playerOptions.preload, + 'loop': playerOptions.loop, + 'muted': playerOptions.muted + + }, options['flashVars']), + + // Merge default parames with ones passed in + params = vjs.obj.merge({ + 'wmode': 'opaque', // Opaque is needed to overlay controls, but can affect playback performance + 'bgcolor': '#000000' // Using bgcolor prevents a white flash when the object is loading + }, options['params']), + + // Merge default attributes with ones passed in + attributes = vjs.obj.merge({ + 'id': objId, + 'name': objId, // Both ID and Name needed or swf to identifty itself + 'class': 'vjs-tech' + }, options['attributes']) + ; + + // If source was supplied pass as a flash var. + if (source) { + if (source.type && vjs.Flash.isStreamingType(source.type)) { + var parts = vjs.Flash.streamToParts(source.src); + flashVars['rtmpConnection'] = encodeURIComponent(parts.connection); + flashVars['rtmpStream'] = encodeURIComponent(parts.stream); + } + else { + flashVars['src'] = encodeURIComponent(vjs.getAbsoluteURL(source.src)); + } + } + + // Add placeholder to player div + vjs.insertFirst(placeHolder, parentEl); + + // Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers + // This allows resetting the playhead when we catch the reload + if (options['startTime']) { + this.ready(function(){ + this.load(); + this.play(); + this.currentTime(options['startTime']); + }); + } + + // Flash iFrame Mode + // In web browsers there are multiple instances where changing the parent element or visibility of a plugin causes the plugin to reload. + // - Firefox just about always. https://bugzilla.mozilla.org/show_bug.cgi?id=90268 (might be fixed by version 13) + // - Webkit when hiding the plugin + // - Webkit and Firefox when using requestFullScreen on a parent element + // Loading the flash plugin into a dynamically generated iFrame gets around most of these issues. + // Issues that remain include hiding the element and requestFullScreen in Firefox specifically + + // There's on particularly annoying issue with this method which is that Firefox throws a security error on an offsite Flash object loaded into a dynamically created iFrame. + // Even though the iframe was inserted into a page on the web, Firefox + Flash considers it a local app trying to access an internet file. + // I tried mulitple ways of setting the iframe src attribute but couldn't find a src that worked well. Tried a real/fake source, in/out of domain. + // Also tried a method from stackoverflow that caused a security error in all browsers. http://stackoverflow.com/questions/2486901/how-to-set-document-domain-for-a-dynamically-generated-iframe + // In the end the solution I found to work was setting the iframe window.location.href right before doing a document.write of the Flash object. + // The only downside of this it seems to trigger another http request to the original page (no matter what's put in the href). Not sure why that is. + + // NOTE (2012-01-29): Cannot get Firefox to load the remote hosted SWF into a dynamically created iFrame + // Firefox 9 throws a security error, unleess you call location.href right before doc.write. + // Not sure why that even works, but it causes the browser to look like it's continuously trying to load the page. + // Firefox 3.6 keeps calling the iframe onload function anytime I write to it, causing an endless loop. + + if (options['iFrameMode'] === true && !vjs.IS_FIREFOX) { + + // Create iFrame with vjs-tech class so it's 100% width/height + var iFrm = vjs.createEl('iframe', { + 'id': objId + '_iframe', + 'name': objId + '_iframe', + 'className': 'vjs-tech', + 'scrolling': 'no', + 'marginWidth': 0, + 'marginHeight': 0, + 'frameBorder': 0 + }); + + // Update ready function names in flash vars for iframe window + flashVars['readyFunction'] = 'ready'; + flashVars['eventProxyFunction'] = 'events'; + flashVars['errorEventProxyFunction'] = 'errors'; + + // Tried multiple methods to get this to work in all browsers + + // Tried embedding the flash object in the page first, and then adding a place holder to the iframe, then replacing the placeholder with the page object. + // The goal here was to try to load the swf URL in the parent page first and hope that got around the firefox security error + // var newObj = vjs.Flash.embed(options['swf'], placeHolder, flashVars, params, attributes); + // (in onload) + // var temp = vjs.createEl('a', { id:'asdf', innerHTML: 'asdf' } ); + // iDoc.body.appendChild(temp); + + // Tried embedding the flash object through javascript in the iframe source. + // This works in webkit but still triggers the firefox security error + // iFrm.src = 'javascript: document.write('"+vjs.Flash.getEmbedCode(options['swf'], flashVars, params, attributes)+"');"; + + // Tried an actual local iframe just to make sure that works, but it kills the easiness of the CDN version if you require the user to host an iframe + // We should add an option to host the iframe locally though, because it could help a lot of issues. + // iFrm.src = "iframe.html"; + + // Wait until iFrame has loaded to write into it. + vjs.on(iFrm, 'load', vjs.bind(this, function(){ + + var iDoc, + iWin = iFrm.contentWindow; + + // The one working method I found was to use the iframe's document.write() to create the swf object + // This got around the security issue in all browsers except firefox. + // I did find a hack where if I call the iframe's window.location.href='', it would get around the security error + // However, the main page would look like it was loading indefinitely (URL bar loading spinner would never stop) + // Plus Firefox 3.6 didn't work no matter what I tried. + // if (vjs.USER_AGENT.match('Firefox')) { + // iWin.location.href = ''; + // } + + // Get the iFrame's document depending on what the browser supports + iDoc = iFrm.contentDocument ? iFrm.contentDocument : iFrm.contentWindow.document; + + // Tried ensuring both document domains were the same, but they already were, so that wasn't the issue. + // Even tried adding /. that was mentioned in a browser security writeup + // document.domain = document.domain+'/.'; + // iDoc.domain = document.domain+'/.'; + + // Tried adding the object to the iframe doc's innerHTML. Security error in all browsers. + // iDoc.body.innerHTML = swfObjectHTML; + + // Tried appending the object to the iframe doc's body. Security error in all browsers. + // iDoc.body.appendChild(swfObject); + + // Using document.write actually got around the security error that browsers were throwing. + // Again, it's a dynamically generated (same domain) iframe, loading an external Flash swf. + // Not sure why that's a security issue, but apparently it is. + iDoc.write(vjs.Flash.getEmbedCode(options['swf'], flashVars, params, attributes)); + + // Setting variables on the window needs to come after the doc write because otherwise they can get reset in some browsers + // So far no issues with swf ready event being called before it's set on the window. + iWin['player'] = this.player_; + + // Create swf ready function for iFrame window + iWin['ready'] = vjs.bind(this.player_, function(currSwf){ + var el = iDoc.getElementById(currSwf), + player = this, + tech = player.tech; + + // Update reference to playback technology element + tech.el_ = el; + + // Make sure swf is actually ready. Sometimes the API isn't actually yet. + vjs.Flash.checkReady(tech); + }); + + // Create event listener for all swf events + iWin['events'] = vjs.bind(this.player_, function(swfID, eventName){ + var player = this; + if (player && player.techName === 'flash') { + player.trigger(eventName); + } + }); + + // Create error listener for all swf errors + iWin['errors'] = vjs.bind(this.player_, function(swfID, eventName){ + vjs.log('Flash Error', eventName); + }); + + })); + + // Replace placeholder with iFrame (it will load now) + placeHolder.parentNode.replaceChild(iFrm, placeHolder); + + // If not using iFrame mode, embed as normal object + } else { + vjs.Flash.embed(options['swf'], placeHolder, flashVars, params, attributes); + } + } +}); + +vjs.Flash.prototype.dispose = function(){ + vjs.MediaTechController.prototype.dispose.call(this); +}; + +vjs.Flash.prototype.play = function(){ + this.el_.vjs_play(); +}; + +vjs.Flash.prototype.pause = function(){ + this.el_.vjs_pause(); +}; + +vjs.Flash.prototype.src = function(src){ + if (vjs.Flash.isStreamingSrc(src)) { + src = vjs.Flash.streamToParts(src); + this.setRtmpConnection(src.connection); + this.setRtmpStream(src.stream); + } + else { + // Make sure source URL is abosolute. + src = vjs.getAbsoluteURL(src); + this.el_.vjs_src(src); + } + + // Currently the SWF doesn't autoplay if you load a source later. + // e.g. Load player w/ no source, wait 2s, set src. + if (this.player_.autoplay()) { + var tech = this; + setTimeout(function(){ tech.play(); }, 0); + } +}; + +vjs.Flash.prototype.currentSrc = function(){ + var src = this.el_.vjs_getProperty('currentSrc'); + // no src, check and see if RTMP + if (src == null) { + var connection = this.rtmpConnection(), + stream = this.rtmpStream(); + + if (connection && stream) { + src = vjs.Flash.streamFromParts(connection, stream); + } + } + return src; +}; + +vjs.Flash.prototype.load = function(){ + this.el_.vjs_load(); +}; + +vjs.Flash.prototype.poster = function(){ + this.el_.vjs_getProperty('poster'); +}; + +vjs.Flash.prototype.buffered = function(){ + return vjs.createTimeRange(0, this.el_.vjs_getProperty('buffered')); +}; + +vjs.Flash.prototype.supportsFullScreen = function(){ + return false; // Flash does not allow fullscreen through javascript +}; + +vjs.Flash.prototype.enterFullScreen = function(){ + return false; +}; + + +// Create setters and getters for attributes +var api = vjs.Flash.prototype, + readWrite = 'rtmpConnection,rtmpStream,preload,currentTime,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted'.split(','), + readOnly = 'error,currentSrc,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks'.split(','); + // Overridden: buffered + +/** + * @this {*} + */ +var createSetter = function(attr){ + var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1); + api['set'+attrUpper] = function(val){ return this.el_.vjs_setProperty(attr, val); }; +}; + +/** + * @this {*} + */ +var createGetter = function(attr){ + api[attr] = function(){ return this.el_.vjs_getProperty(attr); }; +}; + +(function(){ + var i; + // Create getter and setters for all read/write attributes + for (i = 0; i < readWrite.length; i++) { + createGetter(readWrite[i]); + createSetter(readWrite[i]); + } + + // Create getters for read-only attributes + for (i = 0; i < readOnly.length; i++) { + createGetter(readOnly[i]); + } +})(); + +/* Flash Support Testing -------------------------------------------------------- */ + +vjs.Flash.isSupported = function(){ + return vjs.Flash.version()[0] >= 10; + // return swfobject.hasFlashPlayerVersion('10'); +}; + +vjs.Flash.canPlaySource = function(srcObj){ + if (srcObj.type in vjs.Flash.formats || srcObj.type in vjs.Flash.streamingFormats) { return 'maybe'; } +}; + +vjs.Flash.formats = { + 'video/flv': 'FLV', + 'video/x-flv': 'FLV', + 'video/mp4': 'MP4', + 'video/m4v': 'MP4' +}; + +vjs.Flash.streamingFormats = { + 'rtmp/mp4': 'MP4', + 'rtmp/flv': 'FLV' +}; + +vjs.Flash['onReady'] = function(currSwf){ + var el = vjs.el(currSwf); + + // Get player from box + // On firefox reloads, el might already have a player + var player = el['player'] || el.parentNode['player'], + tech = player.tech; + + // Reference player on tech element + el['player'] = player; + + // Update reference to playback technology element + tech.el_ = el; + + vjs.Flash.checkReady(tech); +}; + +// The SWF isn't alwasy ready when it says it is. Sometimes the API functions still need to be added to the object. +// If it's not ready, we set a timeout to check again shortly. +vjs.Flash.checkReady = function(tech){ + + // Check if API property exists + if (tech.el().vjs_getProperty) { + + // If so, tell tech it's ready + tech.triggerReady(); + + // Otherwise wait longer. + } else { + + setTimeout(function(){ + vjs.Flash.checkReady(tech); + }, 50); + + } +}; + +// Trigger events from the swf on the player +vjs.Flash['onEvent'] = function(swfID, eventName){ + var player = vjs.el(swfID)['player']; + player.trigger(eventName); +}; + +// Log errors from the swf +vjs.Flash['onError'] = function(swfID, err){ + var player = vjs.el(swfID)['player']; + player.trigger('error'); + vjs.log('Flash Error', err, swfID); +}; + +// Flash Version Check +vjs.Flash.version = function(){ + var version = '0,0,0'; + + // IE + try { + version = new window.ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1]; + + // other browsers + } catch(e) { + try { + if (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin){ + version = (navigator.plugins['Shockwave Flash 2.0'] || navigator.plugins['Shockwave Flash']).description.replace(/\D+/g, ',').match(/^,?(.+),?$/)[1]; + } + } catch(err) {} + } + return version.split(','); +}; + +// Flash embedding method. Only used in non-iframe mode +vjs.Flash.embed = function(swf, placeHolder, flashVars, params, attributes){ + var code = vjs.Flash.getEmbedCode(swf, flashVars, params, attributes), + + // Get element by embedding code and retrieving created element + obj = vjs.createEl('div', { innerHTML: code }).childNodes[0], + + par = placeHolder.parentNode + ; + + placeHolder.parentNode.replaceChild(obj, placeHolder); + + // IE6 seems to have an issue where it won't initialize the swf object after injecting it. + // This is a dumb fix + var newObj = par.childNodes[0]; + setTimeout(function(){ + newObj.style.display = 'block'; + }, 1000); + + return obj; + +}; + +vjs.Flash.getEmbedCode = function(swf, flashVars, params, attributes){ + + var objTag = '<object type="application/x-shockwave-flash"', + flashVarsString = '', + paramsString = '', + attrsString = ''; + + // Convert flash vars to string + if (flashVars) { + vjs.obj.each(flashVars, function(key, val){ + flashVarsString += (key + '=' + val + '&'); + }); + } + + // Add swf, flashVars, and other default params + params = vjs.obj.merge({ + 'movie': swf, + 'flashvars': flashVarsString, + 'allowScriptAccess': 'always', // Required to talk to swf + 'allowNetworking': 'all' // All should be default, but having security issues. + }, params); + + // Create param tags string + vjs.obj.each(params, function(key, val){ + paramsString += '<param name="'+key+'" value="'+val+'" />'; + }); + + attributes = vjs.obj.merge({ + // Add swf to attributes (need both for IE and Others to work) + 'data': swf, + + // Default to 100% width/height + 'width': '100%', + 'height': '100%' + + }, attributes); + + // Create Attributes string + vjs.obj.each(attributes, function(key, val){ + attrsString += (key + '="' + val + '" '); + }); + + return objTag + attrsString + '>' + paramsString + '</object>'; +}; + +vjs.Flash.streamFromParts = function(connection, stream) { + return connection + '&' + stream; +}; + +vjs.Flash.streamToParts = function(src) { + var parts = { + connection: '', + stream: '' + }; + + if (! src) { + return parts; + } + + // Look for the normal URL separator we expect, '&'. + // If found, we split the URL into two pieces around the + // first '&'. + var connEnd = src.indexOf('&'); + var streamBegin; + if (connEnd !== -1) { + streamBegin = connEnd + 1; + } + else { + // If there's not a '&', we use the last '/' as the delimiter. + connEnd = streamBegin = src.lastIndexOf('/') + 1; + if (connEnd === 0) { + // really, there's not a '/'? + connEnd = streamBegin = src.length; + } + } + parts.connection = src.substring(0, connEnd); + parts.stream = src.substring(streamBegin, src.length); + + return parts; +}; + +vjs.Flash.isStreamingType = function(srcType) { + return srcType in vjs.Flash.streamingFormats; +}; + +// RTMP has four variations, any string starting +// with one of these protocols should be valid +vjs.Flash.RTMP_RE = /^rtmp[set]?:\/\//i; + +vjs.Flash.isStreamingSrc = function(src) { + return vjs.Flash.RTMP_RE.test(src); +}; +/** + * @constructor + */ +vjs.MediaLoader = vjs.Component.extend({ + /** @constructor */ + init: function(player, options, ready){ + vjs.Component.call(this, player, options, ready); + + // If there are no sources when the player is initialized, + // load the first supported playback technology. + if (!player.options_['sources'] || player.options_['sources'].length === 0) { + for (var i=0,j=player.options_['techOrder']; i<j.length; i++) { + var techName = vjs.capitalize(j[i]), + tech = window['videojs'][techName]; + + // Check if the browser supports this technology + if (tech && tech.isSupported()) { + player.loadTech(techName); + break; + } + } + } else { + // // Loop through playback technologies (HTML5, Flash) and check for support. + // // Then load the best source. + // // A few assumptions here: + // // All playback technologies respect preload false. + player.src(player.options_['sources']); + } + } +});/** + * @fileoverview Text Tracks + * Text tracks are tracks of timed text events. + * Captions - text displayed over the video for the hearing impared + * Subtitles - text displayed over the video for those who don't understand langauge in the video + * Chapters - text displayed in a menu allowing the user to jump to particular points (chapters) in the video + * Descriptions (not supported yet) - audio descriptions that are read back to the user by a screen reading device + */ + +// Player Additions - Functions add to the player object for easier access to tracks + +/** + * List of associated text tracks + * @type {Array} + * @private + */ +vjs.Player.prototype.textTracks_; + +/** + * Get an array of associated text tracks. captions, subtitles, chapters, descriptions + * http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks + * @return {Array} Array of track objects + */ +vjs.Player.prototype.textTracks = function(){ + this.textTracks_ = this.textTracks_ || []; + return this.textTracks_; +}; + +/** + * Add a text track + * In addition to the W3C settings we allow adding additional info through options. + * http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-addtexttrack + * @param {String} kind Captions, subtitles, chapters, descriptions, or metadata + * @param {String=} label Optional label + * @param {String=} language Optional language + * @param {Object=} options Additional track options, like src + */ +vjs.Player.prototype.addTextTrack = function(kind, label, language, options){ + var tracks = this.textTracks_ = this.textTracks_ || []; + options = options || {}; + + options['kind'] = kind; + options['label'] = label; + options['language'] = language; + + // HTML5 Spec says default to subtitles. + // Uppercase first letter to match class names + var Kind = vjs.capitalize(kind || 'subtitles'); + + // Create correct texttrack class. CaptionsTrack, etc. + var track = new window['videojs'][Kind + 'Track'](this, options); + + tracks.push(track); + + // If track.dflt() is set, start showing immediately + // TODO: Add a process to deterime the best track to show for the specific kind + // Incase there are mulitple defaulted tracks of the same kind + // Or the user has a set preference of a specific language that should override the default + // if (track.dflt()) { + // this.ready(vjs.bind(track, track.show)); + // } + + return track; +}; + +/** + * Add an array of text tracks. captions, subtitles, chapters, descriptions + * Track objects will be stored in the player.textTracks() array + * @param {Array} trackList Array of track elements or objects (fake track elements) + */ +vjs.Player.prototype.addTextTracks = function(trackList){ + var trackObj; + + for (var i = 0; i < trackList.length; i++) { + trackObj = trackList[i]; + this.addTextTrack(trackObj['kind'], trackObj['label'], trackObj['language'], trackObj); + } + + return this; +}; + +// Show a text track +// disableSameKind: disable all other tracks of the same kind. Value should be a track kind (captions, etc.) +vjs.Player.prototype.showTextTrack = function(id, disableSameKind){ + var tracks = this.textTracks_, + i = 0, + j = tracks.length, + track, showTrack, kind; + + // Find Track with same ID + for (;i<j;i++) { + track = tracks[i]; + if (track.id() === id) { + track.show(); + showTrack = track; + + // Disable tracks of the same kind + } else if (disableSameKind && track.kind() == disableSameKind && track.mode() > 0) { + track.disable(); + } + } + + // Get track kind from shown track or disableSameKind + kind = (showTrack) ? showTrack.kind() : ((disableSameKind) ? disableSameKind : false); + + // Trigger trackchange event, captionstrackchange, subtitlestrackchange, etc. + if (kind) { + this.trigger(kind+'trackchange'); + } + + return this; +}; + +/** + * Track Class + * Contains track methods for loading, showing, parsing cues of tracks + * @param {vjs.Player|Object} player + * @param {Object=} options + * @constructor + */ +vjs.TextTrack = vjs.Component.extend({ + /** @constructor */ + init: function(player, options){ + vjs.Component.call(this, player, options); + + // Apply track info to track object + // Options will often be a track element + + // Build ID if one doesn't exist + this.id_ = options['id'] || ('vjs_' + options['kind'] + '_' + options['language'] + '_' + vjs.guid++); + this.src_ = options['src']; + // 'default' is a reserved keyword in js so we use an abbreviated version + this.dflt_ = options['default'] || options['dflt']; + this.title_ = options['title']; + this.language_ = options['srclang']; + this.label_ = options['label']; + this.cues_ = []; + this.activeCues_ = []; + this.readyState_ = 0; + this.mode_ = 0; + + this.player_.on('fullscreenchange', vjs.bind(this, this.adjustFontSize)); + } +}); + +/** + * Track kind value. Captions, subtitles, etc. + * @private + */ +vjs.TextTrack.prototype.kind_; + +/** + * Get the track kind value + * @return {String} + */ +vjs.TextTrack.prototype.kind = function(){ + return this.kind_; +}; + +/** + * Track src value + * @private + */ +vjs.TextTrack.prototype.src_; + +/** + * Get the track src value + * @return {String} + */ +vjs.TextTrack.prototype.src = function(){ + return this.src_; +}; + +/** + * Track default value + * If default is used, subtitles/captions to start showing + * @private + */ +vjs.TextTrack.prototype.dflt_; + +/** + * Get the track default value + * 'default' is a reserved keyword + * @return {Boolean} + */ +vjs.TextTrack.prototype.dflt = function(){ + return this.dflt_; +}; + +/** + * Track title value + * @private + */ +vjs.TextTrack.prototype.title_; + +/** + * Get the track title value + * @return {String} + */ +vjs.TextTrack.prototype.title = function(){ + return this.title_; +}; + +/** + * Language - two letter string to represent track language, e.g. 'en' for English + * Spec def: readonly attribute DOMString language; + * @private + */ +vjs.TextTrack.prototype.language_; + +/** + * Get the track language value + * @return {String} + */ +vjs.TextTrack.prototype.language = function(){ + return this.language_; +}; + +/** + * Track label e.g. 'English' + * Spec def: readonly attribute DOMString label; + * @private + */ +vjs.TextTrack.prototype.label_; + +/** + * Get the track label value + * @return {String} + */ +vjs.TextTrack.prototype.label = function(){ + return this.label_; +}; + +/** + * All cues of the track. Cues have a startTime, endTime, text, and other properties. + * Spec def: readonly attribute TextTrackCueList cues; + * @private + */ +vjs.TextTrack.prototype.cues_; + +/** + * Get the track cues + * @return {Array} + */ +vjs.TextTrack.prototype.cues = function(){ + return this.cues_; +}; + +/** + * ActiveCues is all cues that are currently showing + * Spec def: readonly attribute TextTrackCueList activeCues; + * @private + */ +vjs.TextTrack.prototype.activeCues_; + +/** + * Get the track active cues + * @return {Array} + */ +vjs.TextTrack.prototype.activeCues = function(){ + return this.activeCues_; +}; + +/** + * ReadyState describes if the text file has been loaded + * const unsigned short NONE = 0; + * const unsigned short LOADING = 1; + * const unsigned short LOADED = 2; + * const unsigned short ERROR = 3; + * readonly attribute unsigned short readyState; + * @private + */ +vjs.TextTrack.prototype.readyState_; + +/** + * Get the track readyState + * @return {Number} + */ +vjs.TextTrack.prototype.readyState = function(){ + return this.readyState_; +}; + +/** + * Mode describes if the track is showing, hidden, or disabled + * const unsigned short OFF = 0; + * const unsigned short HIDDEN = 1; (still triggering cuechange events, but not visible) + * const unsigned short SHOWING = 2; + * attribute unsigned short mode; + * @private + */ +vjs.TextTrack.prototype.mode_; + +/** + * Get the track mode + * @return {Number} + */ +vjs.TextTrack.prototype.mode = function(){ + return this.mode_; +}; + +/** + * Change the font size of the text track to make it larger when playing in fullscreen mode + * and restore it to its normal size when not in fullscreen mode. + */ +vjs.TextTrack.prototype.adjustFontSize = function(){ + if (this.player_.isFullScreen) { + // Scale the font by the same factor as increasing the video width to the full screen window width. + // Additionally, multiply that factor by 1.4, which is the default font size for + // the caption track (from the CSS) + this.el_.style.fontSize = screen.width / this.player_.width() * 1.4 * 100 + '%'; + } else { + // Change the font size of the text track back to its original non-fullscreen size + this.el_.style.fontSize = ''; + } +}; + +/** + * Create basic div to hold cue text + * @return {Element} + */ +vjs.TextTrack.prototype.createEl = function(){ + return vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-' + this.kind_ + ' vjs-text-track' + }); +}; + +/** + * Show: Mode Showing (2) + * Indicates that the text track is active. If no attempt has yet been made to obtain the track's cues, the user agent will perform such an attempt momentarily. + * The user agent is maintaining a list of which cues are active, and events are being fired accordingly. + * In addition, for text tracks whose kind is subtitles or captions, the cues are being displayed over the video as appropriate; + * for text tracks whose kind is descriptions, the user agent is making the cues available to the user in a non-visual fashion; + * and for text tracks whose kind is chapters, the user agent is making available to the user a mechanism by which the user can navigate to any point in the media resource by selecting a cue. + * The showing by default state is used in conjunction with the default attribute on track elements to indicate that the text track was enabled due to that attribute. + * This allows the user agent to override the state if a later track is discovered that is more appropriate per the user's preferences. + */ +vjs.TextTrack.prototype.show = function(){ + this.activate(); + + this.mode_ = 2; + + // Show element. + vjs.Component.prototype.show.call(this); +}; + +/** + * Hide: Mode Hidden (1) + * Indicates that the text track is active, but that the user agent is not actively displaying the cues. + * If no attempt has yet been made to obtain the track's cues, the user agent will perform such an attempt momentarily. + * The user agent is maintaining a list of which cues are active, and events are being fired accordingly. + */ +vjs.TextTrack.prototype.hide = function(){ + // When hidden, cues are still triggered. Disable to stop triggering. + this.activate(); + + this.mode_ = 1; + + // Hide element. + vjs.Component.prototype.hide.call(this); +}; + +/** + * Disable: Mode Off/Disable (0) + * Indicates that the text track is not active. Other than for the purposes of exposing the track in the DOM, the user agent is ignoring the text track. + * No cues are active, no events are fired, and the user agent will not attempt to obtain the track's cues. + */ +vjs.TextTrack.prototype.disable = function(){ + // If showing, hide. + if (this.mode_ == 2) { this.hide(); } + + // Stop triggering cues + this.deactivate(); + + // Switch Mode to Off + this.mode_ = 0; +}; + +/** + * Turn on cue tracking. Tracks that are showing OR hidden are active. + */ +vjs.TextTrack.prototype.activate = function(){ + // Load text file if it hasn't been yet. + if (this.readyState_ === 0) { this.load(); } + + // Only activate if not already active. + if (this.mode_ === 0) { + // Update current cue on timeupdate + // Using unique ID for bind function so other tracks don't remove listener + this.player_.on('timeupdate', vjs.bind(this, this.update, this.id_)); + + // Reset cue time on media end + this.player_.on('ended', vjs.bind(this, this.reset, this.id_)); + + // Add to display + if (this.kind_ === 'captions' || this.kind_ === 'subtitles') { + this.player_.getChild('textTrackDisplay').addChild(this); + } + } +}; + +/** + * Turn off cue tracking. + */ +vjs.TextTrack.prototype.deactivate = function(){ + // Using unique ID for bind function so other tracks don't remove listener + this.player_.off('timeupdate', vjs.bind(this, this.update, this.id_)); + this.player_.off('ended', vjs.bind(this, this.reset, this.id_)); + this.reset(); // Reset + + // Remove from display + this.player_.getChild('textTrackDisplay').removeChild(this); +}; + +// A readiness state +// One of the following: +// +// Not loaded +// Indicates that the text track is known to exist (e.g. it has been declared with a track element), but its cues have not been obtained. +// +// Loading +// Indicates that the text track is loading and there have been no fatal errors encountered so far. Further cues might still be added to the track. +// +// Loaded +// Indicates that the text track has been loaded with no fatal errors. No new cues will be added to the track except if the text track corresponds to a MutableTextTrack object. +// +// Failed to load +// Indicates that the text track was enabled, but when the user agent attempted to obtain it, this failed in some way (e.g. URL could not be resolved, network error, unknown text track format). Some or all of the cues are likely missing and will not be obtained. +vjs.TextTrack.prototype.load = function(){ + + // Only load if not loaded yet. + if (this.readyState_ === 0) { + this.readyState_ = 1; + vjs.get(this.src_, vjs.bind(this, this.parseCues), vjs.bind(this, this.onError)); + } + +}; + +vjs.TextTrack.prototype.onError = function(err){ + this.error = err; + this.readyState_ = 3; + this.trigger('error'); +}; + +// Parse the WebVTT text format for cue times. +// TODO: Separate parser into own class so alternative timed text formats can be used. (TTML, DFXP) +vjs.TextTrack.prototype.parseCues = function(srcContent) { + var cue, time, text, + lines = srcContent.split('\n'), + line = '', id; + + for (var i=1, j=lines.length; i<j; i++) { + // Line 0 should be 'WEBVTT', so skipping i=0 + + line = vjs.trim(lines[i]); // Trim whitespace and linebreaks + + if (line) { // Loop until a line with content + + // First line could be an optional cue ID + // Check if line has the time separator + if (line.indexOf('-->') == -1) { + id = line; + // Advance to next line for timing. + line = vjs.trim(lines[++i]); + } else { + id = this.cues_.length; + } + + // First line - Number + cue = { + id: id, // Cue Number + index: this.cues_.length // Position in Array + }; + + // Timing line + time = line.split(' --> '); + cue.startTime = this.parseCueTime(time[0]); + cue.endTime = this.parseCueTime(time[1]); + + // Additional lines - Cue Text + text = []; + + // Loop until a blank line or end of lines + // Assumeing trim('') returns false for blank lines + while (lines[++i] && (line = vjs.trim(lines[i]))) { + text.push(line); + } + + cue.text = text.join('<br/>'); + + // Add this cue + this.cues_.push(cue); + } + } + + this.readyState_ = 2; + this.trigger('loaded'); +}; + + +vjs.TextTrack.prototype.parseCueTime = function(timeText) { + var parts = timeText.split(':'), + time = 0, + hours, minutes, other, seconds, ms; + + // Check if optional hours place is included + // 00:00:00.000 vs. 00:00.000 + if (parts.length == 3) { + hours = parts[0]; + minutes = parts[1]; + other = parts[2]; + } else { + hours = 0; + minutes = parts[0]; + other = parts[1]; + } + + // Break other (seconds, milliseconds, and flags) by spaces + // TODO: Make additional cue layout settings work with flags + other = other.split(/\s+/); + // Remove seconds. Seconds is the first part before any spaces. + seconds = other.splice(0,1)[0]; + // Could use either . or , for decimal + seconds = seconds.split(/\.|,/); + // Get milliseconds + ms = parseFloat(seconds[1]); + seconds = seconds[0]; + + // hours => seconds + time += parseFloat(hours) * 3600; + // minutes => seconds + time += parseFloat(minutes) * 60; + // Add seconds + time += parseFloat(seconds); + // Add milliseconds + if (ms) { time += ms/1000; } + + return time; +}; + +// Update active cues whenever timeupdate events are triggered on the player. +vjs.TextTrack.prototype.update = function(){ + if (this.cues_.length > 0) { + + // Get curent player time + var time = this.player_.currentTime(); + + // Check if the new time is outside the time box created by the the last update. + if (this.prevChange === undefined || time < this.prevChange || this.nextChange <= time) { + var cues = this.cues_, + + // Create a new time box for this state. + newNextChange = this.player_.duration(), // Start at beginning of the timeline + newPrevChange = 0, // Start at end + + reverse = false, // Set the direction of the loop through the cues. Optimized the cue check. + newCues = [], // Store new active cues. + + // Store where in the loop the current active cues are, to provide a smart starting point for the next loop. + firstActiveIndex, lastActiveIndex, + cue, i; // Loop vars + + // Check if time is going forwards or backwards (scrubbing/rewinding) + // If we know the direction we can optimize the starting position and direction of the loop through the cues array. + if (time >= this.nextChange || this.nextChange === undefined) { // NextChange should happen + // Forwards, so start at the index of the first active cue and loop forward + i = (this.firstActiveIndex !== undefined) ? this.firstActiveIndex : 0; + } else { + // Backwards, so start at the index of the last active cue and loop backward + reverse = true; + i = (this.lastActiveIndex !== undefined) ? this.lastActiveIndex : cues.length - 1; + } + + while (true) { // Loop until broken + cue = cues[i]; + + // Cue ended at this point + if (cue.endTime <= time) { + newPrevChange = Math.max(newPrevChange, cue.endTime); + + if (cue.active) { + cue.active = false; + } + + // No earlier cues should have an active start time. + // Nevermind. Assume first cue could have a duration the same as the video. + // In that case we need to loop all the way back to the beginning. + // if (reverse && cue.startTime) { break; } + + // Cue hasn't started + } else if (time < cue.startTime) { + newNextChange = Math.min(newNextChange, cue.startTime); + + if (cue.active) { + cue.active = false; + } + + // No later cues should have an active start time. + if (!reverse) { break; } + + // Cue is current + } else { + + if (reverse) { + // Add cue to front of array to keep in time order + newCues.splice(0,0,cue); + + // If in reverse, the first current cue is our lastActiveCue + if (lastActiveIndex === undefined) { lastActiveIndex = i; } + firstActiveIndex = i; + } else { + // Add cue to end of array + newCues.push(cue); + + // If forward, the first current cue is our firstActiveIndex + if (firstActiveIndex === undefined) { firstActiveIndex = i; } + lastActiveIndex = i; + } + + newNextChange = Math.min(newNextChange, cue.endTime); + newPrevChange = Math.max(newPrevChange, cue.startTime); + + cue.active = true; + } + + if (reverse) { + // Reverse down the array of cues, break if at first + if (i === 0) { break; } else { i--; } + } else { + // Walk up the array fo cues, break if at last + if (i === cues.length - 1) { break; } else { i++; } + } + + } + + this.activeCues_ = newCues; + this.nextChange = newNextChange; + this.prevChange = newPrevChange; + this.firstActiveIndex = firstActiveIndex; + this.lastActiveIndex = lastActiveIndex; + + this.updateDisplay(); + + this.trigger('cuechange'); + } + } +}; + +// Add cue HTML to display +vjs.TextTrack.prototype.updateDisplay = function(){ + var cues = this.activeCues_, + html = '', + i=0,j=cues.length; + + for (;i<j;i++) { + html += '<span class="vjs-tt-cue">'+cues[i].text+'</span>'; + } + + this.el_.innerHTML = html; +}; + +// Set all loop helper values back +vjs.TextTrack.prototype.reset = function(){ + this.nextChange = 0; + this.prevChange = this.player_.duration(); + this.firstActiveIndex = 0; + this.lastActiveIndex = 0; +}; + +// Create specific track types +/** + * @constructor + */ +vjs.CaptionsTrack = vjs.TextTrack.extend(); +vjs.CaptionsTrack.prototype.kind_ = 'captions'; +// Exporting here because Track creation requires the track kind +// to be available on global object. e.g. new window['videojs'][Kind + 'Track'] + +/** + * @constructor + */ +vjs.SubtitlesTrack = vjs.TextTrack.extend(); +vjs.SubtitlesTrack.prototype.kind_ = 'subtitles'; + +/** + * @constructor + */ +vjs.ChaptersTrack = vjs.TextTrack.extend(); +vjs.ChaptersTrack.prototype.kind_ = 'chapters'; + + +/* Text Track Display +============================================================================= */ +// Global container for both subtitle and captions text. Simple div container. + +/** + * @constructor + */ +vjs.TextTrackDisplay = vjs.Component.extend({ + /** @constructor */ + init: function(player, options, ready){ + vjs.Component.call(this, player, options, ready); + + // This used to be called during player init, but was causing an error + // if a track should show by default and the display hadn't loaded yet. + // Should probably be moved to an external track loader when we support + // tracks that don't need a display. + if (player.options_['tracks'] && player.options_['tracks'].length > 0) { + this.player_.addTextTracks(player.options_['tracks']); + } + } +}); + +vjs.TextTrackDisplay.prototype.createEl = function(){ + return vjs.Component.prototype.createEl.call(this, 'div', { + className: 'vjs-text-track-display' + }); +}; + + +/* Text Track Menu Items +============================================================================= */ +/** + * @constructor + */ +vjs.TextTrackMenuItem = vjs.MenuItem.extend({ + /** @constructor */ + init: function(player, options){ + var track = this.track = options['track']; + + // Modify options for parent MenuItem class's init. + options['label'] = track.label(); + options['selected'] = track.dflt(); + vjs.MenuItem.call(this, player, options); + + this.player_.on(track.kind() + 'trackchange', vjs.bind(this, this.update)); + } +}); + +vjs.TextTrackMenuItem.prototype.onClick = function(){ + vjs.MenuItem.prototype.onClick.call(this); + this.player_.showTextTrack(this.track.id_, this.track.kind()); +}; + +vjs.TextTrackMenuItem.prototype.update = function(){ + this.selected(this.track.mode() == 2); +}; + +/** + * @constructor + */ +vjs.OffTextTrackMenuItem = vjs.TextTrackMenuItem.extend({ + /** @constructor */ + init: function(player, options){ + // Create pseudo track info + // Requires options['kind'] + options['track'] = { + kind: function() { return options['kind']; }, + player: player, + label: function(){ return options['kind'] + ' off'; }, + dflt: function(){ return false; }, + mode: function(){ return false; } + }; + vjs.TextTrackMenuItem.call(this, player, options); + this.selected(true); + } +}); + +vjs.OffTextTrackMenuItem.prototype.onClick = function(){ + vjs.TextTrackMenuItem.prototype.onClick.call(this); + this.player_.showTextTrack(this.track.id_, this.track.kind()); +}; + +vjs.OffTextTrackMenuItem.prototype.update = function(){ + var tracks = this.player_.textTracks(), + i=0, j=tracks.length, track, + off = true; + + for (;i<j;i++) { + track = tracks[i]; + if (track.kind() == this.track.kind() && track.mode() == 2) { + off = false; + } + } + + this.selected(off); +}; + +/* Captions Button +================================================================================ */ +/** + * @constructor + */ +vjs.TextTrackButton = vjs.MenuButton.extend({ + /** @constructor */ + init: function(player, options){ + vjs.MenuButton.call(this, player, options); + + if (this.items.length <= 1) { + this.hide(); + } + } +}); + +// vjs.TextTrackButton.prototype.buttonPressed = false; + +// vjs.TextTrackButton.prototype.createMenu = function(){ +// var menu = new vjs.Menu(this.player_); + +// // Add a title list item to the top +// // menu.el().appendChild(vjs.createEl('li', { +// // className: 'vjs-menu-title', +// // innerHTML: vjs.capitalize(this.kind_), +// // tabindex: -1 +// // })); + +// this.items = this.createItems(); + +// // Add menu items to the menu +// for (var i = 0; i < this.items.length; i++) { +// menu.addItem(this.items[i]); +// } + +// // Add list to element +// this.addChild(menu); + +// return menu; +// }; + +// Create a menu item for each text track +vjs.TextTrackButton.prototype.createItems = function(){ + var items = [], track; + + // Add an OFF menu item to turn all tracks off + items.push(new vjs.OffTextTrackMenuItem(this.player_, { 'kind': this.kind_ })); + + for (var i = 0; i < this.player_.textTracks().length; i++) { + track = this.player_.textTracks()[i]; + if (track.kind() === this.kind_) { + items.push(new vjs.TextTrackMenuItem(this.player_, { + 'track': track + })); + } + } + + return items; +}; + +/** + * @constructor + */ +vjs.CaptionsButton = vjs.TextTrackButton.extend({ + /** @constructor */ + init: function(player, options, ready){ + vjs.TextTrackButton.call(this, player, options, ready); + this.el_.setAttribute('aria-label','Captions Menu'); + } +}); +vjs.CaptionsButton.prototype.kind_ = 'captions'; +vjs.CaptionsButton.prototype.buttonText = 'Captions'; +vjs.CaptionsButton.prototype.className = 'vjs-captions-button'; + +/** + * @constructor + */ +vjs.SubtitlesButton = vjs.TextTrackButton.extend({ + /** @constructor */ + init: function(player, options, ready){ + vjs.TextTrackButton.call(this, player, options, ready); + this.el_.setAttribute('aria-label','Subtitles Menu'); + } +}); +vjs.SubtitlesButton.prototype.kind_ = 'subtitles'; +vjs.SubtitlesButton.prototype.buttonText = 'Subtitles'; +vjs.SubtitlesButton.prototype.className = 'vjs-subtitles-button'; + +// Chapters act much differently than other text tracks +// Cues are navigation vs. other tracks of alternative languages +/** + * @constructor + */ +vjs.ChaptersButton = vjs.TextTrackButton.extend({ + /** @constructor */ + init: function(player, options, ready){ + vjs.TextTrackButton.call(this, player, options, ready); + this.el_.setAttribute('aria-label','Chapters Menu'); + } +}); +vjs.ChaptersButton.prototype.kind_ = 'chapters'; +vjs.ChaptersButton.prototype.buttonText = 'Chapters'; +vjs.ChaptersButton.prototype.className = 'vjs-chapters-button'; + +// Create a menu item for each text track +vjs.ChaptersButton.prototype.createItems = function(){ + var items = [], track; + + for (var i = 0; i < this.player_.textTracks().length; i++) { + track = this.player_.textTracks()[i]; + if (track.kind() === this.kind_) { + items.push(new vjs.TextTrackMenuItem(this.player_, { + 'track': track + })); + } + } + + return items; +}; + +vjs.ChaptersButton.prototype.createMenu = function(){ + var tracks = this.player_.textTracks(), + i = 0, + j = tracks.length, + track, chaptersTrack, + items = this.items = []; + + for (;i<j;i++) { + track = tracks[i]; + if (track.kind() == this.kind_ && track.dflt()) { + if (track.readyState() < 2) { + this.chaptersTrack = track; + track.on('loaded', vjs.bind(this, this.createMenu)); + return; + } else { + chaptersTrack = track; + break; + } + } + } + + var menu = this.menu = new vjs.Menu(this.player_); + + menu.el_.appendChild(vjs.createEl('li', { + className: 'vjs-menu-title', + innerHTML: vjs.capitalize(this.kind_), + tabindex: -1 + })); + + if (chaptersTrack) { + var cues = chaptersTrack.cues_, cue, mi; + i = 0; + j = cues.length; + + for (;i<j;i++) { + cue = cues[i]; + + mi = new vjs.ChaptersTrackMenuItem(this.player_, { + 'track': chaptersTrack, + 'cue': cue + }); + + items.push(mi); + + menu.addChild(mi); + } + } + + if (this.items.length > 0) { + this.show(); + } + + return menu; +}; + + +/** + * @constructor + */ +vjs.ChaptersTrackMenuItem = vjs.MenuItem.extend({ + /** @constructor */ + init: function(player, options){ + var track = this.track = options['track'], + cue = this.cue = options['cue'], + currentTime = player.currentTime(); + + // Modify options for parent MenuItem class's init. + options['label'] = cue.text; + options['selected'] = (cue.startTime <= currentTime && currentTime < cue.endTime); + vjs.MenuItem.call(this, player, options); + + track.on('cuechange', vjs.bind(this, this.update)); + } +}); + +vjs.ChaptersTrackMenuItem.prototype.onClick = function(){ + vjs.MenuItem.prototype.onClick.call(this); + this.player_.currentTime(this.cue.startTime); + this.update(this.cue.startTime); +}; + +vjs.ChaptersTrackMenuItem.prototype.update = function(){ + var cue = this.cue, + currentTime = this.player_.currentTime(); + + // vjs.log(currentTime, cue.startTime); + this.selected(cue.startTime <= currentTime && currentTime < cue.endTime); +}; + +// Add Buttons to controlBar +vjs.obj.merge(vjs.ControlBar.prototype.options_['children'], { + 'subtitlesButton': {}, + 'captionsButton': {}, + 'chaptersButton': {} +}); + +// vjs.Cue = vjs.Component.extend({ +// /** @constructor */ +// init: function(player, options){ +// vjs.Component.call(this, player, options); +// } +// }); +/** + * @fileoverview Add JSON support + * @suppress {undefinedVars} + * (Compiler doesn't like JSON not being declared) + */ + +/** + * Javascript JSON implementation + * (Parse Method Only) + * https://github.com/douglascrockford/JSON-js/blob/master/json2.js + * Only using for parse method when parsing data-setup attribute JSON. + * @type {Object} + * @suppress {undefinedVars} + */ +vjs.JSON; + +/** + * @suppress {undefinedVars} + */ +if (typeof window.JSON !== 'undefined' && window.JSON.parse === 'function') { + vjs.JSON = window.JSON; + +} else { + vjs.JSON = {}; + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + + vjs.JSON.parse = function (text, reviver) { + var j; + + function walk(holder, key) { + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + + if (/^[\],:{}\s]*$/ + .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') + .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + + j = eval('(' + text + ')'); + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + + throw new SyntaxError('JSON.parse(): invalid or malformed JSON data'); + }; +} +/** + * @fileoverview Functions for automatically setting up a player + * based on the data-setup attribute of the video tag + */ + +// Automatically set up any tags that have a data-setup attribute +vjs.autoSetup = function(){ + var options, vid, player, + vids = document.getElementsByTagName('video'); + + // Check if any media elements exist + if (vids && vids.length > 0) { + + for (var i=0,j=vids.length; i<j; i++) { + vid = vids[i]; + + // Check if element exists, has getAttribute func. + // IE seems to consider typeof el.getAttribute == 'object' instead of 'function' like expected, at least when loading the player immediately. + if (vid && vid.getAttribute) { + + // Make sure this player hasn't already been set up. + if (vid['player'] === undefined) { + options = vid.getAttribute('data-setup'); + + // Check if data-setup attr exists. + // We only auto-setup if they've added the data-setup attr. + if (options !== null) { + + // Parse options JSON + // If empty string, make it a parsable json object. + options = vjs.JSON.parse(options || '{}'); + + // Create new video.js instance. + player = videojs(vid, options); + } + } + + // If getAttribute isn't defined, we need to wait for the DOM. + } else { + vjs.autoSetupTimeout(1); + break; + } + } + + // No videos were found, so keep looping unless page is finisehd loading. + } else if (!vjs.windowLoaded) { + vjs.autoSetupTimeout(1); + } +}; + +// Pause to let the DOM keep processing +vjs.autoSetupTimeout = function(wait){ + setTimeout(vjs.autoSetup, wait); +}; + +if (document.readyState === 'complete') { + vjs.windowLoaded = true; +} else { + vjs.one(window, 'load', function(){ + vjs.windowLoaded = true; + }); +} + +// Run Auto-load players +// You have to wait at least once in case this script is loaded after your video in the DOM (weird behavior only with minified version) +vjs.autoSetupTimeout(1); +vjs.plugin = function(name, init){ + vjs.Player.prototype[name] = init; +}; diff --git a/extlib/video-js/video.js b/extlib/video-js/video.js new file mode 100644 index 00000000..8c2621d6 --- /dev/null +++ b/extlib/video-js/video.js @@ -0,0 +1,127 @@ +/*! Video.js v4.2.1 Copyright 2013 Brightcove, Inc. https://github.com/videojs/video.js/blob/master/LICENSE */ (function() {var b=void 0,f=!0,j=null,l=!1;function m(){return function(){}}function p(a){return function(){return this[a]}}function q(a){return function(){return a}}var t;document.createElement("video");document.createElement("audio");document.createElement("track");function u(a,c,d){if("string"===typeof a){0===a.indexOf("#")&&(a=a.slice(1));if(u.wa[a])return u.wa[a];a=u.v(a)}if(!a||!a.nodeName)throw new TypeError("The element or ID supplied is not valid. (videojs)");return a.player||new u.w(a,c,d)}var v=u; +window.Qd=window.Rd=u;u.Rb="4.2";u.Bc="https:"==document.location.protocol?"https://":"http://";u.options={techOrder:["html5","flash"],html5:{},flash:{},width:300,height:150,defaultVolume:0,children:{mediaLoader:{},posterImage:{},textTrackDisplay:{},loadingSpinner:{},bigPlayButton:{},controlBar:{}},notSupportedMessage:'Sorry, no compatible source and playback technology were found for this video. Try using another browser like <a href="http://bit.ly/ccMUEC">Chrome</a> or download the latest <a href="http://adobe.ly/mwfN1">Adobe Flash Player</a>.'}; +"GENERATED_CDN_VSN"!==u.Rb&&(v.options.flash.swf=u.Bc+"vjs.zencdn.net/"+u.Rb+"/video-js.swf");u.wa={};u.ka=u.CoreObject=m();u.ka.extend=function(a){var c,d;a=a||{};c=a.init||a.i||this.prototype.init||this.prototype.i||m();d=function(){c.apply(this,arguments)};d.prototype=u.k.create(this.prototype);d.prototype.constructor=d;d.extend=u.ka.extend;d.create=u.ka.create;for(var e in a)a.hasOwnProperty(e)&&(d.prototype[e]=a[e]);return d}; +u.ka.create=function(){var a=u.k.create(this.prototype);this.apply(a,arguments);return a};u.d=function(a,c,d){var e=u.getData(a);e.z||(e.z={});e.z[c]||(e.z[c]=[]);d.s||(d.s=u.s++);e.z[c].push(d);e.W||(e.disabled=l,e.W=function(c){if(!e.disabled){c=u.gc(c);var d=e.z[c.type];if(d)for(var d=d.slice(0),k=0,r=d.length;k<r&&!c.lc();k++)d[k].call(a,c)}});1==e.z[c].length&&(document.addEventListener?a.addEventListener(c,e.W,l):document.attachEvent&&a.attachEvent("on"+c,e.W))}; +u.n=function(a,c,d){if(u.kc(a)){var e=u.getData(a);if(e.z)if(c){var g=e.z[c];if(g){if(d){if(d.s)for(e=0;e<g.length;e++)g[e].s===d.s&&g.splice(e--,1)}else e.z[c]=[];u.dc(a,c)}}else for(g in e.z)c=g,e.z[c]=[],u.dc(a,c)}};u.dc=function(a,c){var d=u.getData(a);0===d.z[c].length&&(delete d.z[c],document.removeEventListener?a.removeEventListener(c,d.W,l):document.detachEvent&&a.detachEvent("on"+c,d.W));u.Ab(d.z)&&(delete d.z,delete d.W,delete d.disabled);u.Ab(d)&&u.qc(a)}; +u.gc=function(a){function c(){return f}function d(){return l}if(!a||!a.Bb){var e=a||window.event;a={};for(var g in e)"layerX"!==g&&"layerY"!==g&&(a[g]=e[g]);a.target||(a.target=a.srcElement||document);a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;a.preventDefault=function(){e.preventDefault&&e.preventDefault();a.returnValue=l;a.zb=c};a.zb=d;a.stopPropagation=function(){e.stopPropagation&&e.stopPropagation();a.cancelBubble=f;a.Bb=c};a.Bb=d;a.stopImmediatePropagation=function(){e.stopImmediatePropagation&& +e.stopImmediatePropagation();a.lc=c;a.stopPropagation()};a.lc=d;if(a.clientX!=j){g=document.documentElement;var h=document.body;a.pageX=a.clientX+(g&&g.scrollLeft||h&&h.scrollLeft||0)-(g&&g.clientLeft||h&&h.clientLeft||0);a.pageY=a.clientY+(g&&g.scrollTop||h&&h.scrollTop||0)-(g&&g.clientTop||h&&h.clientTop||0)}a.which=a.charCode||a.keyCode;a.button!=j&&(a.button=a.button&1?0:a.button&4?1:a.button&2?2:0)}return a}; +u.j=function(a,c){var d=u.kc(a)?u.getData(a):{},e=a.parentNode||a.ownerDocument;"string"===typeof c&&(c={type:c,target:a});c=u.gc(c);d.W&&d.W.call(a,c);if(e&&!c.Bb()&&c.bubbles!==l)u.j(e,c);else if(!e&&!c.zb()&&(d=u.getData(c.target),c.target[c.type])){d.disabled=f;if("function"===typeof c.target[c.type])c.target[c.type]();d.disabled=l}return!c.zb()};u.U=function(a,c,d){function e(){u.n(a,c,e);d.apply(this,arguments)}e.s=d.s=d.s||u.s++;u.d(a,c,e)};var w=Object.prototype.hasOwnProperty; +u.e=function(a,c){var d,e;d=document.createElement(a||"div");for(e in c)w.call(c,e)&&(-1!==e.indexOf("aria-")||"role"==e?d.setAttribute(e,c[e]):d[e]=c[e]);return d};u.$=function(a){return a.charAt(0).toUpperCase()+a.slice(1)};u.k={};u.k.create=Object.create||function(a){function c(){}c.prototype=a;return new c};u.k.ta=function(a,c,d){for(var e in a)w.call(a,e)&&c.call(d||this,e,a[e])};u.k.B=function(a,c){if(!c)return a;for(var d in c)w.call(c,d)&&(a[d]=c[d]);return a}; +u.k.fc=function(a,c){var d,e,g;a=u.k.copy(a);for(d in c)w.call(c,d)&&(e=a[d],g=c[d],a[d]=u.k.mc(e)&&u.k.mc(g)?u.k.fc(e,g):c[d]);return a};u.k.copy=function(a){return u.k.B({},a)};u.k.mc=function(a){return!!a&&"object"===typeof a&&"[object Object]"===a.toString()&&a.constructor===Object};u.bind=function(a,c,d){function e(){return c.apply(a,arguments)}c.s||(c.s=u.s++);e.s=d?d+"_"+c.s:c.s;return e};u.qa={};u.s=1;u.expando="vdata"+(new Date).getTime(); +u.getData=function(a){var c=a[u.expando];c||(c=a[u.expando]=u.s++,u.qa[c]={});return u.qa[c]};u.kc=function(a){a=a[u.expando];return!(!a||u.Ab(u.qa[a]))};u.qc=function(a){var c=a[u.expando];if(c){delete u.qa[c];try{delete a[u.expando]}catch(d){a.removeAttribute?a.removeAttribute(u.expando):a[u.expando]=j}}};u.Ab=function(a){for(var c in a)if(a[c]!==j)return l;return f};u.m=function(a,c){-1==(" "+a.className+" ").indexOf(" "+c+" ")&&(a.className=""===a.className?c:a.className+" "+c)}; +u.t=function(a,c){var d,e;if(-1!=a.className.indexOf(c)){d=a.className.split(" ");for(e=d.length-1;0<=e;e--)d[e]===c&&d.splice(e,1);a.className=d.join(" ")}};u.ma=u.e("video");u.G=navigator.userAgent;u.Hc=/iPhone/i.test(u.G);u.Gc=/iPad/i.test(u.G);u.Ic=/iPod/i.test(u.G);u.Fc=u.Hc||u.Gc||u.Ic;var aa=u,x;var y=u.G.match(/OS (\d+)_/i);x=y&&y[1]?y[1]:b;aa.Cd=x;u.Dc=/Android/i.test(u.G);var ba=u,z;var A=u.G.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i),B,C; +A?(B=A[1]&&parseFloat(A[1]),C=A[2]&&parseFloat(A[2]),z=B&&C?parseFloat(A[1]+"."+A[2]):B?B:j):z=j;ba.Cc=z;u.Jc=u.Dc&&/webkit/i.test(u.G)&&2.3>u.Cc;u.Ec=/Firefox/i.test(u.G);u.Dd=/Chrome/i.test(u.G);u.Mc="ontouchstart"in window;u.wb=function(a){var c,d,e,g;c={};if(a&&a.attributes&&0<a.attributes.length){d=a.attributes;for(var h=d.length-1;0<=h;h--){e=d[h].name;g=d[h].value;if("boolean"===typeof a[e]||-1!==",autoplay,controls,loop,muted,default,".indexOf(","+e+","))g=g!==j?f:l;c[e]=g}}return c}; +u.Hd=function(a,c){var d="";document.defaultView&&document.defaultView.getComputedStyle?d=document.defaultView.getComputedStyle(a,"").getPropertyValue(c):a.currentStyle&&(d=a["client"+c.substr(0,1).toUpperCase()+c.substr(1)]+"px");return d};u.yb=function(a,c){c.firstChild?c.insertBefore(a,c.firstChild):c.appendChild(a)};u.Nb={};u.v=function(a){0===a.indexOf("#")&&(a=a.slice(1));return document.getElementById(a)}; +u.Ka=function(a,c){c=c||a;var d=Math.floor(a%60),e=Math.floor(a/60%60),g=Math.floor(a/3600),h=Math.floor(c/60%60),k=Math.floor(c/3600);if(isNaN(a)||Infinity===a)g=e=d="-";g=0<g||0<k?g+":":"";return g+(((g||10<=h)&&10>e?"0"+e:e)+":")+(10>d?"0"+d:d)};u.Pc=function(){document.body.focus();document.onselectstart=q(l)};u.yd=function(){document.onselectstart=q(f)};u.trim=function(a){return(a+"").replace(/^\s+|\s+$/g,"")};u.round=function(a,c){c||(c=0);return Math.round(a*Math.pow(10,c))/Math.pow(10,c)}; +u.sb=function(a,c){return{length:1,start:function(){return a},end:function(){return c}}}; +u.get=function(a,c,d){var e,g;"undefined"===typeof XMLHttpRequest&&(window.XMLHttpRequest=function(){try{return new window.ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(a){}try{return new window.ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(c){}try{return new window.ActiveXObject("Msxml2.XMLHTTP")}catch(d){}throw Error("This browser does not support XMLHttpRequest.");});g=new XMLHttpRequest;try{g.open("GET",a)}catch(h){d(h)}e=0===a.indexOf("file:")||0===window.location.href.indexOf("file:")&&-1===a.indexOf("http"); +g.onreadystatechange=function(){4===g.readyState&&(200===g.status||e&&0===g.status?c(g.responseText):d&&d())};try{g.send()}catch(k){d&&d(k)}};u.qd=function(a){try{var c=window.localStorage||l;c&&(c.volume=a)}catch(d){22==d.code||1014==d.code?u.log("LocalStorage Full (VideoJS)",d):18==d.code?u.log("LocalStorage not allowed (VideoJS)",d):u.log("LocalStorage Error (VideoJS)",d)}};u.ic=function(a){a.match(/^https?:\/\//)||(a=u.e("div",{innerHTML:'<a href="'+a+'">x</a>'}).firstChild.href);return a}; +u.log=function(){u.log.history=u.log.history||[];u.log.history.push(arguments);window.console&&window.console.log(Array.prototype.slice.call(arguments))};u.Xc=function(a){var c,d;a.getBoundingClientRect&&a.parentNode&&(c=a.getBoundingClientRect());if(!c)return{left:0,top:0};a=document.documentElement;d=document.body;return{left:c.left+(window.pageXOffset||d.scrollLeft)-(a.clientLeft||d.clientLeft||0),top:c.top+(window.pageYOffset||d.scrollTop)-(a.clientTop||d.clientTop||0)}}; +u.c=u.ka.extend({i:function(a,c,d){this.b=a;this.g=u.k.copy(this.g);c=this.options(c);this.Q=c.id||(c.el&&c.el.id?c.el.id:a.id()+"_component_"+u.s++);this.cd=c.name||j;this.a=c.el||this.e();this.H=[];this.pb={};this.V={};if((a=this.g)&&a.children){var e=this;u.k.ta(a.children,function(a,c){c!==l&&!c.loadEvent&&(e[a]=e.Z(a,c))})}this.M(d)}});t=u.c.prototype; +t.D=function(){this.j("dispose");if(this.H)for(var a=this.H.length-1;0<=a;a--)this.H[a].D&&this.H[a].D();this.V=this.pb=this.H=j;this.n();this.a.parentNode&&this.a.parentNode.removeChild(this.a);u.qc(this.a);this.a=j};t.L=p("b");t.options=function(a){return a===b?this.g:this.g=u.k.fc(this.g,a)};t.e=function(a,c){return u.e(a,c)};t.v=p("a");t.id=p("Q");t.name=p("cd");t.children=p("H"); +t.Z=function(a,c){var d,e;"string"===typeof a?(e=a,c=c||{},d=c.componentClass||u.$(e),c.name=e,d=new window.videojs[d](this.b||this,c)):d=a;this.H.push(d);"function"===typeof d.id&&(this.pb[d.id()]=d);(e=e||d.name&&d.name())&&(this.V[e]=d);"function"===typeof d.el&&d.el()&&(this.ra||this.a).appendChild(d.el());return d}; +t.removeChild=function(a){"string"===typeof a&&(a=this.V[a]);if(a&&this.H){for(var c=l,d=this.H.length-1;0<=d;d--)if(this.H[d]===a){c=f;this.H.splice(d,1);break}c&&(this.pb[a.id]=j,this.V[a.name]=j,(c=a.v())&&c.parentNode===(this.ra||this.a)&&(this.ra||this.a).removeChild(a.v()))}};t.T=q("");t.d=function(a,c){u.d(this.a,a,u.bind(this,c));return this};t.n=function(a,c){u.n(this.a,a,c);return this};t.U=function(a,c){u.U(this.a,a,u.bind(this,c));return this};t.j=function(a,c){u.j(this.a,a,c);return this}; +t.M=function(a){a&&(this.aa?a.call(this):(this.Ra===b&&(this.Ra=[]),this.Ra.push(a)));return this};t.Ta=function(){this.aa=f;var a=this.Ra;if(a&&0<a.length){for(var c=0,d=a.length;c<d;c++)a[c].call(this);this.Ra=[];this.j("ready")}};t.m=function(a){u.m(this.a,a);return this};t.t=function(a){u.t(this.a,a);return this};t.show=function(){this.a.style.display="block";return this};t.C=function(){this.a.style.display="none";return this};function D(a){a.t("vjs-lock-showing")} +t.disable=function(){this.C();this.show=m()};t.width=function(a,c){return E(this,"width",a,c)};t.height=function(a,c){return E(this,"height",a,c)};t.Tc=function(a,c){return this.width(a,f).height(c)};function E(a,c,d,e){if(d!==b)return a.a.style[c]=-1!==(""+d).indexOf("%")||-1!==(""+d).indexOf("px")?d:"auto"===d?"":d+"px",e||a.j("resize"),a;if(!a.a)return 0;d=a.a.style[c];e=d.indexOf("px");return-1!==e?parseInt(d.slice(0,e),10):parseInt(a.a["offset"+u.$(c)],10)} +u.q=u.c.extend({i:function(a,c){u.c.call(this,a,c);var d=l;this.d("touchstart",function(a){a.preventDefault();d=f});this.d("touchmove",function(){d=l});var e=this;this.d("touchend",function(a){d&&e.p(a);a.preventDefault()});this.d("click",this.p);this.d("focus",this.Na);this.d("blur",this.Ma)}});t=u.q.prototype; +t.e=function(a,c){c=u.k.B({className:this.T(),innerHTML:'<div class="vjs-control-content"><span class="vjs-control-text">'+(this.pa||"Need Text")+"</span></div>",nd:"button","aria-live":"polite",tabIndex:0},c);return u.c.prototype.e.call(this,a,c)};t.T=function(){return"vjs-control "+u.c.prototype.T.call(this)};t.p=m();t.Na=function(){u.d(document,"keyup",u.bind(this,this.ba))};t.ba=function(a){if(32==a.which||13==a.which)a.preventDefault(),this.p()}; +t.Ma=function(){u.n(document,"keyup",u.bind(this,this.ba))};u.O=u.c.extend({i:function(a,c){u.c.call(this,a,c);this.Oc=this.V[this.g.barName];this.handle=this.V[this.g.handleName];a.d(this.oc,u.bind(this,this.update));this.d("mousedown",this.Oa);this.d("touchstart",this.Oa);this.d("focus",this.Na);this.d("blur",this.Ma);this.d("click",this.p);this.b.d("controlsvisible",u.bind(this,this.update));a.M(u.bind(this,this.update));this.P={}}});t=u.O.prototype; +t.e=function(a,c){c=c||{};c.className+=" vjs-slider";c=u.k.B({nd:"slider","aria-valuenow":0,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0},c);return u.c.prototype.e.call(this,a,c)};t.Oa=function(a){a.preventDefault();u.Pc();this.P.move=u.bind(this,this.Gb);this.P.end=u.bind(this,this.Hb);u.d(document,"mousemove",this.P.move);u.d(document,"mouseup",this.P.end);u.d(document,"touchmove",this.P.move);u.d(document,"touchend",this.P.end);this.Gb(a)}; +t.Hb=function(){u.yd();u.n(document,"mousemove",this.P.move,l);u.n(document,"mouseup",this.P.end,l);u.n(document,"touchmove",this.P.move,l);u.n(document,"touchend",this.P.end,l);this.update()};t.update=function(){if(this.a){var a,c=this.xb(),d=this.handle,e=this.Oc;isNaN(c)&&(c=0);a=c;if(d){a=this.a.offsetWidth;var g=d.v().offsetWidth;a=g?g/a:0;c*=1-a;a=c+a/2;d.v().style.left=u.round(100*c,2)+"%"}e.v().style.width=u.round(100*a,2)+"%"}}; +function F(a,c){var d,e,g,h;d=a.a;e=u.Xc(d);h=g=d.offsetWidth;d=a.handle;if(a.g.zd)return h=e.top,e=c.changedTouches?c.changedTouches[0].pageY:c.pageY,d&&(d=d.v().offsetHeight,h+=d/2,g-=d),Math.max(0,Math.min(1,(h-e+g)/g));g=e.left;e=c.changedTouches?c.changedTouches[0].pageX:c.pageX;d&&(d=d.v().offsetWidth,g+=d/2,h-=d);return Math.max(0,Math.min(1,(e-g)/h))}t.Na=function(){u.d(document,"keyup",u.bind(this,this.ba))}; +t.ba=function(a){37==a.which?(a.preventDefault(),this.uc()):39==a.which&&(a.preventDefault(),this.vc())};t.Ma=function(){u.n(document,"keyup",u.bind(this,this.ba))};t.p=function(a){a.stopImmediatePropagation();a.preventDefault()};u.ea=u.c.extend();u.ea.prototype.defaultValue=0;u.ea.prototype.e=function(a,c){c=c||{};c.className+=" vjs-slider-handle";c=u.k.B({innerHTML:'<span class="vjs-control-text">'+this.defaultValue+"</span>"},c);return u.c.prototype.e.call(this,"div",c)};u.la=u.c.extend(); +function ca(a,c){a.Z(c);c.d("click",u.bind(a,function(){D(this)}))}u.la.prototype.e=function(){var a=this.options().Rc||"ul";this.ra=u.e(a,{className:"vjs-menu-content"});a=u.c.prototype.e.call(this,"div",{append:this.ra,className:"vjs-menu"});a.appendChild(this.ra);u.d(a,"click",function(a){a.preventDefault();a.stopImmediatePropagation()});return a};u.N=u.q.extend({i:function(a,c){u.q.call(this,a,c);this.selected(c.selected)}}); +u.N.prototype.e=function(a,c){return u.q.prototype.e.call(this,"li",u.k.B({className:"vjs-menu-item",innerHTML:this.g.label},c))};u.N.prototype.p=function(){this.selected(f)};u.N.prototype.selected=function(a){a?(this.m("vjs-selected"),this.a.setAttribute("aria-selected",f)):(this.t("vjs-selected"),this.a.setAttribute("aria-selected",l))}; +u.R=u.q.extend({i:function(a,c){u.q.call(this,a,c);this.va=this.Ja();this.Z(this.va);this.J&&0===this.J.length&&this.C();this.d("keyup",this.ba);this.a.setAttribute("aria-haspopup",f);this.a.setAttribute("role","button")}});t=u.R.prototype;t.oa=l;t.Ja=function(){var a=new u.la(this.b);this.options().title&&a.v().appendChild(u.e("li",{className:"vjs-menu-title",innerHTML:u.$(this.A),wd:-1}));if(this.J=this.createItems())for(var c=0;c<this.J.length;c++)ca(a,this.J[c]);return a};t.sa=m(); +t.T=function(){return this.className+" vjs-menu-button "+u.q.prototype.T.call(this)};t.Na=m();t.Ma=m();t.p=function(){this.U("mouseout",u.bind(this,function(){D(this.va);this.a.blur()}));this.oa?G(this):H(this)};t.ba=function(a){a.preventDefault();32==a.which||13==a.which?this.oa?G(this):H(this):27==a.which&&this.oa&&G(this)};function H(a){a.oa=f;a.va.m("vjs-lock-showing");a.a.setAttribute("aria-pressed",f);a.J&&0<a.J.length&&a.J[0].v().focus()} +function G(a){a.oa=l;D(a.va);a.a.setAttribute("aria-pressed",l)} +u.w=u.c.extend({i:function(a,c,d){this.F=a;c=u.k.B(da(a),c);this.u={};this.pc=c.poster;this.rb=c.controls;a.controls=l;u.c.call(this,this,c,d);this.controls()?this.m("vjs-controls-enabled"):this.m("vjs-controls-disabled");this.U("play",function(a){u.j(this.a,{type:"firstplay",target:this.a})||(a.preventDefault(),a.stopPropagation(),a.stopImmediatePropagation())});this.d("ended",this.ed);this.d("play",this.Jb);this.d("firstplay",this.fd);this.d("pause",this.Ib);this.d("progress",this.hd);this.d("durationchange", +this.dd);this.d("error",this.Fb);this.d("fullscreenchange",this.gd);u.wa[this.Q]=this;c.plugins&&u.k.ta(c.plugins,function(a,c){this[a](c)},this);var e,g,h,k;e=this.rc;a=function(){e();clearInterval(g);g=setInterval(u.bind(this,e),250)};c=function(){e();clearInterval(g)};this.d("mousedown",a);this.d("mousemove",e);this.d("mouseup",c);this.d("keydown",e);this.d("keyup",e);this.d("touchstart",a);this.d("touchmove",e);this.d("touchend",c);this.d("touchcancel",c);h=setInterval(u.bind(this,function(){this.ja&& +(this.ja=l,I(this,f),clearTimeout(k),k=setTimeout(u.bind(this,function(){this.ja||I(this,l)}),2E3))}),250);this.d("dispose",function(){clearInterval(h);clearTimeout(k)})}});t=u.w.prototype;t.g=u.options;t.D=function(){this.j("dispose");this.n("dispose");u.wa[this.Q]=j;this.F&&this.F.player&&(this.F.player=j);this.a&&this.a.player&&(this.a.player=j);clearInterval(this.Qa);this.ya();this.h&&this.h.D();u.c.prototype.D.call(this)}; +function da(a){var c={sources:[],tracks:[]};u.k.B(c,u.wb(a));if(a.hasChildNodes()){var d,e,g,h;a=a.childNodes;g=0;for(h=a.length;g<h;g++)d=a[g],e=d.nodeName.toLowerCase(),"source"===e?c.sources.push(u.wb(d)):"track"===e&&c.tracks.push(u.wb(d))}return c} +t.e=function(){var a=this.a=u.c.prototype.e.call(this,"div"),c=this.F;c.removeAttribute("width");c.removeAttribute("height");if(c.hasChildNodes()){var d,e,g,h,k;d=c.childNodes;e=d.length;for(k=[];e--;)g=d[e],h=g.nodeName.toLowerCase(),("source"===h||"track"===h)&&k.push(g);for(d=0;d<k.length;d++)c.removeChild(k[d])}c.id=c.id||"vjs_video_"+u.s++;a.id=c.id;a.className=c.className;c.id+="_html5_api";c.className="vjs-tech";c.player=a.player=this;this.m("vjs-paused");this.width(this.g.width,f);this.height(this.g.height, +f);c.parentNode&&c.parentNode.insertBefore(a,c);u.yb(c,a);return a}; +function J(a,c,d){a.h?(a.aa=l,a.h.D(),a.Db&&(a.Db=l,clearInterval(a.Qa)),a.Eb&&K(a),a.h=l):"Html5"!==c&&a.F&&(a.a.removeChild(a.F),a.F.player=j,a.F=j);a.ia=c;a.aa=l;var e=u.k.B({source:d,parentEl:a.a},a.g[c.toLowerCase()]);d&&(d.src==a.u.src&&0<a.u.currentTime&&(e.startTime=a.u.currentTime),a.u.src=d.src);a.h=new window.videojs[c](a,e);a.h.M(function(){this.b.Ta();if(!this.l.progressEvents){var a=this.b;a.Db=f;a.Qa=setInterval(u.bind(a,function(){this.u.kb<this.buffered().end(0)?this.j("progress"): +1==this.Ia()&&(clearInterval(this.Qa),this.j("progress"))}),500);a.h.U("progress",function(){this.l.progressEvents=f;var a=this.b;a.Db=l;clearInterval(a.Qa)})}this.l.timeupdateEvents||(a=this.b,a.Eb=f,a.d("play",a.yc),a.d("pause",a.ya),a.h.U("timeupdate",function(){this.l.timeupdateEvents=f;K(this.b)}))})}function K(a){a.Eb=l;a.ya();a.n("play",a.yc);a.n("pause",a.ya)}t.yc=function(){this.ec&&this.ya();this.ec=setInterval(u.bind(this,function(){this.j("timeupdate")}),250)};t.ya=function(){clearInterval(this.ec)}; +t.ed=function(){this.g.loop&&(this.currentTime(0),this.play())};t.Jb=function(){u.t(this.a,"vjs-paused");u.m(this.a,"vjs-playing")};t.fd=function(){this.g.starttime&&this.currentTime(this.g.starttime);this.m("vjs-has-started")};t.Ib=function(){u.t(this.a,"vjs-playing");u.m(this.a,"vjs-paused")};t.hd=function(){1==this.Ia()&&this.j("loadedalldata")};t.dd=function(){this.duration(L(this,"duration"))};t.Fb=function(a){u.log("Video Error",a)};t.gd=function(){this.I?this.m("vjs-fullscreen"):this.t("vjs-fullscreen")}; +function M(a,c,d){if(a.h&&!a.h.aa)a.h.M(function(){this[c](d)});else try{a.h[c](d)}catch(e){throw u.log(e),e;}}function L(a,c){if(a.h&&a.h.aa)try{return a.h[c]()}catch(d){throw a.h[c]===b?u.log("Video.js: "+c+" method not defined for "+a.ia+" playback technology.",d):"TypeError"==d.name?(u.log("Video.js: "+c+" unavailable on "+a.ia+" playback technology element.",d),a.h.aa=l):u.log(d),d;}}t.play=function(){M(this,"play");return this};t.pause=function(){M(this,"pause");return this}; +t.paused=function(){return L(this,"paused")===l?l:f};t.currentTime=function(a){return a!==b?(this.u.nc=a,M(this,"setCurrentTime",a),this.Eb&&this.j("timeupdate"),this):this.u.currentTime=L(this,"currentTime")||0};t.duration=function(a){return a!==b?(this.u.duration=parseFloat(a),this):this.u.duration};t.buffered=function(){var a=L(this,"buffered"),c=a.length-1,d=this.u.kb=this.u.kb||0;a&&(0<=c&&a.end(c)!==d)&&(d=a.end(c),this.u.kb=d);return u.sb(0,d)}; +t.Ia=function(){return this.duration()?this.buffered().end(0)/this.duration():0};t.volume=function(a){if(a!==b)return a=Math.max(0,Math.min(1,parseFloat(a))),this.u.volume=a,M(this,"setVolume",a),u.qd(a),this;a=parseFloat(L(this,"volume"));return isNaN(a)?1:a};t.muted=function(a){return a!==b?(M(this,"setMuted",a),this):L(this,"muted")||l};t.Sa=function(){return L(this,"supportsFullScreen")||l}; +t.xa=function(){var a=u.Nb.xa;this.I=f;a?(u.d(document,a.ub,u.bind(this,function(c){this.I=document[a.I];this.I===l&&u.n(document,a.ub,arguments.callee);this.j("fullscreenchange")})),this.a[a.sc]()):this.h.Sa()?M(this,"enterFullScreen"):(this.Zc=f,this.Uc=document.documentElement.style.overflow,u.d(document,"keydown",u.bind(this,this.hc)),document.documentElement.style.overflow="hidden",u.m(document.body,"vjs-full-window"),this.j("enterFullWindow"),this.j("fullscreenchange"));return this}; +t.nb=function(){var a=u.Nb.xa;this.I=l;if(a)document[a.mb]();else this.h.Sa()?M(this,"exitFullScreen"):(N(this),this.j("fullscreenchange"));return this};t.hc=function(a){27===a.keyCode&&(this.I===f?this.nb():N(this))};function N(a){a.Zc=l;u.n(document,"keydown",a.hc);document.documentElement.style.overflow=a.Uc;u.t(document.body,"vjs-full-window");a.j("exitFullWindow")} +t.src=function(a){if(a instanceof Array){var c;a:{c=a;for(var d=0,e=this.g.techOrder;d<e.length;d++){var g=u.$(e[d]),h=window.videojs[g];if(h.isSupported())for(var k=0,r=c;k<r.length;k++){var n=r[k];if(h.canPlaySource(n)){c={source:n,h:g};break a}}}c=l}c?(a=c.source,c=c.h,c==this.ia?this.src(a):J(this,c,a)):this.a.appendChild(u.e("p",{innerHTML:this.options().notSupportedMessage}))}else a instanceof Object?window.videojs[this.ia].canPlaySource(a)?this.src(a.src):this.src([a]):(this.u.src=a,this.aa? +(M(this,"src",a),"auto"==this.g.preload&&this.load(),this.g.autoplay&&this.play()):this.M(function(){this.src(a)}));return this};t.load=function(){M(this,"load");return this};t.currentSrc=function(){return L(this,"currentSrc")||this.u.src||""};t.Pa=function(a){return a!==b?(M(this,"setPreload",a),this.g.preload=a,this):L(this,"preload")};t.autoplay=function(a){return a!==b?(M(this,"setAutoplay",a),this.g.autoplay=a,this):L(this,"autoplay")}; +t.loop=function(a){return a!==b?(M(this,"setLoop",a),this.g.loop=a,this):L(this,"loop")};t.poster=function(a){a!==b&&(this.pc=a);return this.pc};t.controls=function(a){return a!==b?(a=!!a,this.rb!==a&&((this.rb=a)?(this.t("vjs-controls-disabled"),this.m("vjs-controls-enabled"),this.j("controlsenabled")):(this.t("vjs-controls-enabled"),this.m("vjs-controls-disabled"),this.j("controlsdisabled"))),this):this.rb};u.w.prototype.Qb;t=u.w.prototype; +t.Pb=function(a){return a!==b?(a=!!a,this.Qb!==a&&((this.Qb=a)?(this.m("vjs-using-native-controls"),this.j("usingnativecontrols")):(this.t("vjs-using-native-controls"),this.j("usingcustomcontrols"))),this):this.Qb};t.error=function(){return L(this,"error")};t.seeking=function(){return L(this,"seeking")};t.ja=f;t.rc=function(){this.ja=f};t.Ob=f; +function I(a,c){return c!==b?(c=!!c,c!==a.Ob&&((a.Ob=c)?(a.ja=f,a.t("vjs-user-inactive"),a.m("vjs-user-active"),a.j("useractive")):(a.ja=l,a.h.U("mousemove",function(a){a.stopPropagation();a.preventDefault()}),a.t("vjs-user-active"),a.m("vjs-user-inactive"),a.j("userinactive"))),a):a.Ob}var O,P,Q;Q=document.createElement("div");P={}; +Q.Ed!==b?(P.sc="requestFullscreen",P.mb="exitFullscreen",P.ub="fullscreenchange",P.I="fullScreen"):(document.mozCancelFullScreen?(O="moz",P.I=O+"FullScreen"):(O="webkit",P.I=O+"IsFullScreen"),Q[O+"RequestFullScreen"]&&(P.sc=O+"RequestFullScreen",P.mb=O+"CancelFullScreen"),P.ub=O+"fullscreenchange");document[P.mb]&&(u.Nb.xa=P);u.Ea=u.c.extend(); +u.Ea.prototype.g={Jd:"play",children:{playToggle:{},currentTimeDisplay:{},timeDivider:{},durationDisplay:{},remainingTimeDisplay:{},progressControl:{},fullscreenToggle:{},volumeControl:{},muteToggle:{}}};u.Ea.prototype.e=function(){return u.e("div",{className:"vjs-control-bar"})};u.Wb=u.q.extend({i:function(a,c){u.q.call(this,a,c);a.d("play",u.bind(this,this.Jb));a.d("pause",u.bind(this,this.Ib))}});t=u.Wb.prototype;t.pa="Play";t.T=function(){return"vjs-play-control "+u.q.prototype.T.call(this)}; +t.p=function(){this.b.paused()?this.b.play():this.b.pause()};t.Jb=function(){u.t(this.a,"vjs-paused");u.m(this.a,"vjs-playing");this.a.children[0].children[0].innerHTML="Pause"};t.Ib=function(){u.t(this.a,"vjs-playing");u.m(this.a,"vjs-paused");this.a.children[0].children[0].innerHTML="Play"};u.Xa=u.c.extend({i:function(a,c){u.c.call(this,a,c);a.d("timeupdate",u.bind(this,this.Ba))}}); +u.Xa.prototype.e=function(){var a=u.c.prototype.e.call(this,"div",{className:"vjs-current-time vjs-time-controls vjs-control"});this.content=u.e("div",{className:"vjs-current-time-display",innerHTML:'<span class="vjs-control-text">Current Time </span>0:00',"aria-live":"off"});a.appendChild(u.e("div").appendChild(this.content));return a}; +u.Xa.prototype.Ba=function(){var a=this.b.Lb?this.b.u.currentTime:this.b.currentTime();this.content.innerHTML='<span class="vjs-control-text">Current Time </span>'+u.Ka(a,this.b.duration())};u.Ya=u.c.extend({i:function(a,c){u.c.call(this,a,c);a.d("timeupdate",u.bind(this,this.Ba))}}); +u.Ya.prototype.e=function(){var a=u.c.prototype.e.call(this,"div",{className:"vjs-duration vjs-time-controls vjs-control"});this.content=u.e("div",{className:"vjs-duration-display",innerHTML:'<span class="vjs-control-text">Duration Time </span>0:00',"aria-live":"off"});a.appendChild(u.e("div").appendChild(this.content));return a};u.Ya.prototype.Ba=function(){var a=this.b.duration();a&&(this.content.innerHTML='<span class="vjs-control-text">Duration Time </span>'+u.Ka(a))}; +u.$b=u.c.extend({i:function(a,c){u.c.call(this,a,c)}});u.$b.prototype.e=function(){return u.c.prototype.e.call(this,"div",{className:"vjs-time-divider",innerHTML:"<div><span>/</span></div>"})};u.eb=u.c.extend({i:function(a,c){u.c.call(this,a,c);a.d("timeupdate",u.bind(this,this.Ba))}}); +u.eb.prototype.e=function(){var a=u.c.prototype.e.call(this,"div",{className:"vjs-remaining-time vjs-time-controls vjs-control"});this.content=u.e("div",{className:"vjs-remaining-time-display",innerHTML:'<span class="vjs-control-text">Remaining Time </span>-0:00',"aria-live":"off"});a.appendChild(u.e("div").appendChild(this.content));return a};u.eb.prototype.Ba=function(){this.b.duration()&&(this.content.innerHTML='<span class="vjs-control-text">Remaining Time </span>-'+u.Ka(this.b.duration()-this.b.currentTime()))}; +u.Fa=u.q.extend({i:function(a,c){u.q.call(this,a,c)}});u.Fa.prototype.pa="Fullscreen";u.Fa.prototype.T=function(){return"vjs-fullscreen-control "+u.q.prototype.T.call(this)};u.Fa.prototype.p=function(){this.b.I?(this.b.nb(),this.a.children[0].children[0].innerHTML="Fullscreen"):(this.b.xa(),this.a.children[0].children[0].innerHTML="Non-Fullscreen")};u.cb=u.c.extend({i:function(a,c){u.c.call(this,a,c)}});u.cb.prototype.g={children:{seekBar:{}}}; +u.cb.prototype.e=function(){return u.c.prototype.e.call(this,"div",{className:"vjs-progress-control vjs-control"})};u.Xb=u.O.extend({i:function(a,c){u.O.call(this,a,c);a.d("timeupdate",u.bind(this,this.Aa));a.M(u.bind(this,this.Aa))}});t=u.Xb.prototype;t.g={children:{loadProgressBar:{},playProgressBar:{},seekHandle:{}},barName:"playProgressBar",handleName:"seekHandle"};t.oc="timeupdate";t.e=function(){return u.O.prototype.e.call(this,"div",{className:"vjs-progress-holder","aria-label":"video progress bar"})}; +t.Aa=function(){var a=this.b.Lb?this.b.u.currentTime:this.b.currentTime();this.a.setAttribute("aria-valuenow",u.round(100*this.xb(),2));this.a.setAttribute("aria-valuetext",u.Ka(a,this.b.duration()))};t.xb=function(){var a;"Flash"===this.b.ia&&this.b.seeking()?(a=this.b.u,a=a.nc?a.nc:this.b.currentTime()):a=this.b.currentTime();return a/this.b.duration()};t.Oa=function(a){u.O.prototype.Oa.call(this,a);this.b.Lb=f;this.Ad=!this.b.paused();this.b.pause()}; +t.Gb=function(a){a=F(this,a)*this.b.duration();a==this.b.duration()&&(a-=0.1);this.b.currentTime(a)};t.Hb=function(a){u.O.prototype.Hb.call(this,a);this.b.Lb=l;this.Ad&&this.b.play()};t.vc=function(){this.b.currentTime(this.b.currentTime()+5)};t.uc=function(){this.b.currentTime(this.b.currentTime()-5)};u.$a=u.c.extend({i:function(a,c){u.c.call(this,a,c);a.d("progress",u.bind(this,this.update))}});u.$a.prototype.e=function(){return u.c.prototype.e.call(this,"div",{className:"vjs-load-progress",innerHTML:'<span class="vjs-control-text">Loaded: 0%</span>'})}; +u.$a.prototype.update=function(){this.a.style&&(this.a.style.width=u.round(100*this.b.Ia(),2)+"%")};u.Vb=u.c.extend({i:function(a,c){u.c.call(this,a,c)}});u.Vb.prototype.e=function(){return u.c.prototype.e.call(this,"div",{className:"vjs-play-progress",innerHTML:'<span class="vjs-control-text">Progress: 0%</span>'})};u.fb=u.ea.extend();u.fb.prototype.defaultValue="00:00";u.fb.prototype.e=function(){return u.ea.prototype.e.call(this,"div",{className:"vjs-seek-handle"})}; +u.hb=u.c.extend({i:function(a,c){u.c.call(this,a,c);a.h&&(a.h.l&&a.h.l.volumeControl===l)&&this.m("vjs-hidden");a.d("loadstart",u.bind(this,function(){a.h.l&&a.h.l.volumeControl===l?this.m("vjs-hidden"):this.t("vjs-hidden")}))}});u.hb.prototype.g={children:{volumeBar:{}}};u.hb.prototype.e=function(){return u.c.prototype.e.call(this,"div",{className:"vjs-volume-control vjs-control"})}; +u.gb=u.O.extend({i:function(a,c){u.O.call(this,a,c);a.d("volumechange",u.bind(this,this.Aa));a.M(u.bind(this,this.Aa));setTimeout(u.bind(this,this.update),0)}});t=u.gb.prototype;t.Aa=function(){this.a.setAttribute("aria-valuenow",u.round(100*this.b.volume(),2));this.a.setAttribute("aria-valuetext",u.round(100*this.b.volume(),2)+"%")};t.g={children:{volumeLevel:{},volumeHandle:{}},barName:"volumeLevel",handleName:"volumeHandle"};t.oc="volumechange"; +t.e=function(){return u.O.prototype.e.call(this,"div",{className:"vjs-volume-bar","aria-label":"volume level"})};t.Gb=function(a){this.b.volume(F(this,a))};t.xb=function(){return this.b.muted()?0:this.b.volume()};t.vc=function(){this.b.volume(this.b.volume()+0.1)};t.uc=function(){this.b.volume(this.b.volume()-0.1)};u.ac=u.c.extend({i:function(a,c){u.c.call(this,a,c)}});u.ac.prototype.e=function(){return u.c.prototype.e.call(this,"div",{className:"vjs-volume-level",innerHTML:'<span class="vjs-control-text"></span>'})}; +u.ib=u.ea.extend();u.ib.prototype.defaultValue="00:00";u.ib.prototype.e=function(){return u.ea.prototype.e.call(this,"div",{className:"vjs-volume-handle"})};u.da=u.q.extend({i:function(a,c){u.q.call(this,a,c);a.d("volumechange",u.bind(this,this.update));a.h&&(a.h.l&&a.h.l.volumeControl===l)&&this.m("vjs-hidden");a.d("loadstart",u.bind(this,function(){a.h.l&&a.h.l.volumeControl===l?this.m("vjs-hidden"):this.t("vjs-hidden")}))}}); +u.da.prototype.e=function(){return u.q.prototype.e.call(this,"div",{className:"vjs-mute-control vjs-control",innerHTML:'<div><span class="vjs-control-text">Mute</span></div>'})};u.da.prototype.p=function(){this.b.muted(this.b.muted()?l:f)}; +u.da.prototype.update=function(){var a=this.b.volume(),c=3;0===a||this.b.muted()?c=0:0.33>a?c=1:0.67>a&&(c=2);this.b.muted()?"Unmute"!=this.a.children[0].children[0].innerHTML&&(this.a.children[0].children[0].innerHTML="Unmute"):"Mute"!=this.a.children[0].children[0].innerHTML&&(this.a.children[0].children[0].innerHTML="Mute");for(a=0;4>a;a++)u.t(this.a,"vjs-vol-"+a);u.m(this.a,"vjs-vol-"+c)}; +u.na=u.R.extend({i:function(a,c){u.R.call(this,a,c);a.d("volumechange",u.bind(this,this.update));a.h&&(a.h.l&&a.h.l.zc===l)&&this.m("vjs-hidden");a.d("loadstart",u.bind(this,function(){a.h.l&&a.h.l.zc===l?this.m("vjs-hidden"):this.t("vjs-hidden")}));this.m("vjs-menu-button")}});u.na.prototype.Ja=function(){var a=new u.la(this.b,{Rc:"div"}),c=new u.gb(this.b,u.k.B({zd:f},this.g.Sd));a.Z(c);return a};u.na.prototype.p=function(){u.da.prototype.p.call(this);u.R.prototype.p.call(this)}; +u.na.prototype.e=function(){return u.q.prototype.e.call(this,"div",{className:"vjs-volume-menu-button vjs-menu-button vjs-control",innerHTML:'<div><span class="vjs-control-text">Mute</span></div>'})};u.na.prototype.update=u.da.prototype.update;u.bb=u.q.extend({i:function(a,c){u.q.call(this,a,c);(!a.poster()||!a.controls())&&this.C();a.d("play",u.bind(this,this.C))}}); +u.bb.prototype.e=function(){var a=u.e("div",{className:"vjs-poster",tabIndex:-1}),c=this.b.poster();c&&("backgroundSize"in a.style?a.style.backgroundImage='url("'+c+'")':a.appendChild(u.e("img",{src:c})));return a};u.bb.prototype.p=function(){this.L().controls()&&this.b.play()}; +u.Ub=u.c.extend({i:function(a,c){u.c.call(this,a,c);a.d("canplay",u.bind(this,this.C));a.d("canplaythrough",u.bind(this,this.C));a.d("playing",u.bind(this,this.C));a.d("seeked",u.bind(this,this.C));a.d("seeking",u.bind(this,this.show));a.d("seeked",u.bind(this,this.C));a.d("error",u.bind(this,this.show));a.d("waiting",u.bind(this,this.show))}});u.Ub.prototype.e=function(){return u.c.prototype.e.call(this,"div",{className:"vjs-loading-spinner"})};u.Va=u.q.extend(); +u.Va.prototype.e=function(){return u.q.prototype.e.call(this,"div",{className:"vjs-big-play-button",innerHTML:"<span></span>","aria-label":"play video"})};u.Va.prototype.p=function(){this.b.play()}; +u.r=u.c.extend({i:function(a,c,d){u.c.call(this,a,c,d);var e,g;g=this;e=this.L();a=function(){if(e.controls()&&!e.Pb()){var a,c;g.d("mousedown",g.p);g.d("touchstart",function(a){a.preventDefault();a.stopPropagation();c=I(this.b)});a=function(a){a.stopPropagation();c&&this.b.rc()};g.d("touchmove",a);g.d("touchleave",a);g.d("touchcancel",a);g.d("touchend",a);var d,n,s;d=0;g.d("touchstart",function(){d=(new Date).getTime();s=f});a=function(){s=l};g.d("touchmove",a);g.d("touchleave",a);g.d("touchcancel", +a);g.d("touchend",function(){s===f&&(n=(new Date).getTime()-d,250>n&&this.j("tap"))});g.d("tap",g.jd)}};c=u.bind(g,g.md);this.M(a);e.d("controlsenabled",a);e.d("controlsdisabled",c)}});u.r.prototype.md=function(){this.n("tap");this.n("touchstart");this.n("touchmove");this.n("touchleave");this.n("touchcancel");this.n("touchend");this.n("click");this.n("mousedown")};u.r.prototype.p=function(a){0===a.button&&this.L().controls()&&(this.L().paused()?this.L().play():this.L().pause())}; +u.r.prototype.jd=function(){I(this.L(),!I(this.L()))};u.r.prototype.l={volumeControl:f,fullscreenResize:l,progressEvents:l,timeupdateEvents:l};u.media={};u.media.Ua="play pause paused currentTime setCurrentTime duration buffered volume setVolume muted setMuted width height supportsFullScreen enterFullScreen src load currentSrc preload setPreload autoplay setAutoplay loop setLoop error networkState readyState seeking initialTime startOffsetTime played seekable ended videoTracks audioTracks videoWidth videoHeight textTracks defaultPlaybackRate playbackRate mediaGroup controller controls defaultMuted".split(" "); +function ea(){var a=u.media.Ua[i];return function(){throw Error('The "'+a+"\" method is not available on the playback technology's API");}}for(var i=u.media.Ua.length-1;0<=i;i--)u.r.prototype[u.media.Ua[i]]=ea(); +u.o=u.r.extend({i:function(a,c,d){this.l.volumeControl=u.o.Qc();this.l.movingMediaElementInDOM=!u.Fc;this.l.fullscreenResize=f;u.r.call(this,a,c,d);(c=c.source)&&this.a.currentSrc==c.src?a.j("loadstart"):c&&(this.a.src=c.src);if(u.Mc&&a.options().nativeControlsForTouch!==l){var e,g,h,k;e=this;g=this.L();c=g.controls();e.a.controls=!!c;h=function(){e.a.controls=f};k=function(){e.a.controls=l};g.d("controlsenabled",h);g.d("controlsdisabled",k);c=function(){g.n("controlsenabled",h);g.n("controlsdisabled", +k)};e.d("dispose",c);g.d("usingcustomcontrols",c);g.Pb(f)}a.M(function(){this.F&&(this.g.autoplay&&this.paused())&&(delete this.F.poster,this.play())});for(a=u.o.Za.length-1;0<=a;a--)u.d(this.a,u.o.Za[a],u.bind(this.b,this.Wc));this.Ta()}});t=u.o.prototype;t.D=function(){u.r.prototype.D.call(this)}; +t.e=function(){var a=this.b,c=a.F;if(!c||this.l.movingMediaElementInDOM===l)c?(c.player=j,a.F=j,a.v().removeChild(c),c=c.cloneNode(l)):c=u.e("video",{id:a.id()+"_html5_api",className:"vjs-tech"}),c.player=a,u.yb(c,a.v());for(var d=["autoplay","preload","loop","muted"],e=d.length-1;0<=e;e--){var g=d[e];a.g[g]!==j&&(c[g]=a.g[g])}return c};t.Wc=function(a){this.j(a);a.stopPropagation()};t.play=function(){this.a.play()};t.pause=function(){this.a.pause()};t.paused=function(){return this.a.paused}; +t.currentTime=function(){return this.a.currentTime};t.pd=function(a){try{this.a.currentTime=a}catch(c){u.log(c,"Video is not ready. (Video.js)")}};t.duration=function(){return this.a.duration||0};t.buffered=function(){return this.a.buffered};t.volume=function(){return this.a.volume};t.ud=function(a){this.a.volume=a};t.muted=function(){return this.a.muted};t.sd=function(a){this.a.muted=a};t.width=function(){return this.a.offsetWidth};t.height=function(){return this.a.offsetHeight}; +t.Sa=function(){return"function"==typeof this.a.webkitEnterFullScreen&&(/Android/.test(u.G)||!/Chrome|Mac OS X 10.5/.test(u.G))?f:l};t.src=function(a){this.a.src=a};t.load=function(){this.a.load()};t.currentSrc=function(){return this.a.currentSrc};t.Pa=function(){return this.a.Pa};t.td=function(a){this.a.Pa=a};t.autoplay=function(){return this.a.autoplay};t.od=function(a){this.a.autoplay=a};t.controls=function(){return this.a.controls};t.loop=function(){return this.a.loop}; +t.rd=function(a){this.a.loop=a};t.error=function(){return this.a.error};t.seeking=function(){return this.a.seeking};u.o.isSupported=function(){return!!u.ma.canPlayType};u.o.lb=function(a){try{return!!u.ma.canPlayType(a.type)}catch(c){return""}};u.o.Qc=function(){var a=u.ma.volume;u.ma.volume=a/2+0.1;return a!==u.ma.volume};u.o.Za="loadstart suspend abort error emptied stalled loadedmetadata loadeddata canplay canplaythrough playing waiting seeking seeked ended durationchange timeupdate progress play pause ratechange volumechange".split(" "); +u.Jc&&(document.createElement("video").constructor.prototype.canPlayType=function(a){return a&&-1!=a.toLowerCase().indexOf("video/mp4")?"maybe":""}); +u.f=u.r.extend({i:function(a,c,d){u.r.call(this,a,c,d);var e=c.source;d=c.parentEl;var g=this.a=u.e("div",{id:a.id()+"_temp_flash"}),h=a.id()+"_flash_api";a=a.g;var k=u.k.B({readyFunction:"videojs.Flash.onReady",eventProxyFunction:"videojs.Flash.onEvent",errorEventProxyFunction:"videojs.Flash.onError",autoplay:a.autoplay,preload:a.Pa,loop:a.loop,muted:a.muted},c.flashVars),r=u.k.B({wmode:"opaque",bgcolor:"#000000"},c.params),n=u.k.B({id:h,name:h,"class":"vjs-tech"},c.attributes);e&&(e.type&&u.f.ad(e.type)? +(a=u.f.wc(e.src),k.rtmpConnection=encodeURIComponent(a.qb),k.rtmpStream=encodeURIComponent(a.Mb)):k.src=encodeURIComponent(u.ic(e.src)));u.yb(g,d);c.startTime&&this.M(function(){this.load();this.play();this.currentTime(c.startTime)});if(c.iFrameMode===f&&!u.Ec){var s=u.e("iframe",{id:h+"_iframe",name:h+"_iframe",className:"vjs-tech",scrolling:"no",marginWidth:0,marginHeight:0,frameBorder:0});k.readyFunction="ready";k.eventProxyFunction="events";k.errorEventProxyFunction="errors";u.d(s,"load",u.bind(this, +function(){var a,d=s.contentWindow;a=s.contentDocument?s.contentDocument:s.contentWindow.document;a.write(u.f.jc(c.swf,k,r,n));d.player=this.b;d.ready=u.bind(this.b,function(c){var d=this.h;d.a=a.getElementById(c);u.f.ob(d)});d.events=u.bind(this.b,function(a,c){this&&"flash"===this.ia&&this.j(c)});d.errors=u.bind(this.b,function(a,c){u.log("Flash Error",c)})}));g.parentNode.replaceChild(s,g)}else u.f.Vc(c.swf,g,k,r,n)}});t=u.f.prototype;t.D=function(){u.r.prototype.D.call(this)};t.play=function(){this.a.vjs_play()}; +t.pause=function(){this.a.vjs_pause()};t.src=function(a){u.f.$c(a)?(a=u.f.wc(a),this.Nd(a.qb),this.Od(a.Mb)):(a=u.ic(a),this.a.vjs_src(a));if(this.b.autoplay()){var c=this;setTimeout(function(){c.play()},0)}};t.currentSrc=function(){var a=this.a.vjs_getProperty("currentSrc");if(a==j){var c=this.Ld(),d=this.Md();c&&d&&(a=u.f.vd(c,d))}return a};t.load=function(){this.a.vjs_load()};t.poster=function(){this.a.vjs_getProperty("poster")};t.buffered=function(){return u.sb(0,this.a.vjs_getProperty("buffered"))}; +t.Sa=q(l);var R=u.f.prototype,S="rtmpConnection rtmpStream preload currentTime defaultPlaybackRate playbackRate autoplay loop mediaGroup controller controls volume muted defaultMuted".split(" "),T="error currentSrc networkState readyState seeking initialTime duration startOffsetTime paused played seekable ended videoTracks audioTracks videoWidth videoHeight textTracks".split(" "); +function fa(){var a=S[U],c=a.charAt(0).toUpperCase()+a.slice(1);R["set"+c]=function(c){return this.a.vjs_setProperty(a,c)}}function V(a){R[a]=function(){return this.a.vjs_getProperty(a)}}var U;for(U=0;U<S.length;U++)V(S[U]),fa();for(U=0;U<T.length;U++)V(T[U]);u.f.isSupported=function(){return 10<=u.f.version()[0]};u.f.lb=function(a){if(a.type in u.f.Yc||a.type in u.f.xc)return"maybe"};u.f.Yc={"video/flv":"FLV","video/x-flv":"FLV","video/mp4":"MP4","video/m4v":"MP4"};u.f.xc={"rtmp/mp4":"MP4","rtmp/flv":"FLV"}; +u.f.onReady=function(a){a=u.v(a);var c=a.player||a.parentNode.player,d=c.h;a.player=c;d.a=a;u.f.ob(d)};u.f.ob=function(a){a.v().vjs_getProperty?a.Ta():setTimeout(function(){u.f.ob(a)},50)};u.f.onEvent=function(a,c){u.v(a).player.j(c)};u.f.onError=function(a,c){u.v(a).player.j("error");u.log("Flash Error",c,a)}; +u.f.version=function(){var a="0,0,0";try{a=(new window.ActiveXObject("ShockwaveFlash.ShockwaveFlash")).GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(c){try{navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin&&(a=(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1])}catch(d){}}return a.split(",")}; +u.f.Vc=function(a,c,d,e,g){a=u.f.jc(a,d,e,g);a=u.e("div",{innerHTML:a}).childNodes[0];d=c.parentNode;c.parentNode.replaceChild(a,c);var h=d.childNodes[0];setTimeout(function(){h.style.display="block"},1E3)}; +u.f.jc=function(a,c,d,e){var g="",h="",k="";c&&u.k.ta(c,function(a,c){g+=a+"="+c+"&"});d=u.k.B({movie:a,flashvars:g,allowScriptAccess:"always",allowNetworking:"all"},d);u.k.ta(d,function(a,c){h+='<param name="'+a+'" value="'+c+'" />'});e=u.k.B({data:a,width:"100%",height:"100%"},e);u.k.ta(e,function(a,c){k+=a+'="'+c+'" '});return'<object type="application/x-shockwave-flash"'+k+">"+h+"</object>"};u.f.vd=function(a,c){return a+"&"+c}; +u.f.wc=function(a){var c={qb:"",Mb:""};if(!a)return c;var d=a.indexOf("&"),e;-1!==d?e=d+1:(d=e=a.lastIndexOf("/")+1,0===d&&(d=e=a.length));c.qb=a.substring(0,d);c.Mb=a.substring(e,a.length);return c};u.f.ad=function(a){return a in u.f.xc};u.f.Lc=/^rtmp[set]?:\/\//i;u.f.$c=function(a){return u.f.Lc.test(a)}; +u.Kc=u.c.extend({i:function(a,c,d){u.c.call(this,a,c,d);if(!a.g.sources||0===a.g.sources.length){c=0;for(d=a.g.techOrder;c<d.length;c++){var e=u.$(d[c]),g=window.videojs[e];if(g&&g.isSupported()){J(a,e);break}}}else a.src(a.g.sources)}});function W(a){a.za=a.za||[];return a.za}function X(a,c,d){for(var e=a.za,g=0,h=e.length,k,r;g<h;g++)k=e[g],k.id()===c?(k.show(),r=k):d&&(k.K()==d&&0<k.mode())&&k.disable();(c=r?r.K():d?d:l)&&a.j(c+"trackchange")} +u.X=u.c.extend({i:function(a,c){u.c.call(this,a,c);this.Q=c.id||"vjs_"+c.kind+"_"+c.language+"_"+u.s++;this.tc=c.src;this.Sc=c["default"]||c.dflt;this.xd=c.title;this.Id=c.srclang;this.bd=c.label;this.fa=[];this.bc=[];this.ga=this.ha=0;this.b.d("fullscreenchange",u.bind(this,this.Nc))}});t=u.X.prototype;t.K=p("A");t.src=p("tc");t.tb=p("Sc");t.title=p("xd");t.label=p("bd");t.readyState=p("ha");t.mode=p("ga");t.Nc=function(){this.a.style.fontSize=this.b.I?140*(screen.width/this.b.width())+"%":""}; +t.e=function(){return u.c.prototype.e.call(this,"div",{className:"vjs-"+this.A+" vjs-text-track"})};t.show=function(){Y(this);this.ga=2;u.c.prototype.show.call(this)};t.C=function(){Y(this);this.ga=1;u.c.prototype.C.call(this)};t.disable=function(){2==this.ga&&this.C();this.b.n("timeupdate",u.bind(this,this.update,this.Q));this.b.n("ended",u.bind(this,this.reset,this.Q));this.reset();this.b.V.textTrackDisplay.removeChild(this);this.ga=0}; +function Y(a){0===a.ha&&a.load();0===a.ga&&(a.b.d("timeupdate",u.bind(a,a.update,a.Q)),a.b.d("ended",u.bind(a,a.reset,a.Q)),("captions"===a.A||"subtitles"===a.A)&&a.b.V.textTrackDisplay.Z(a))}t.load=function(){0===this.ha&&(this.ha=1,u.get(this.tc,u.bind(this,this.kd),u.bind(this,this.Fb)))};t.Fb=function(a){this.error=a;this.ha=3;this.j("error")}; +t.kd=function(a){var c,d;a=a.split("\n");for(var e="",g=1,h=a.length;g<h;g++)if(e=u.trim(a[g])){-1==e.indexOf("--\x3e")?(c=e,e=u.trim(a[++g])):c=this.fa.length;c={id:c,index:this.fa.length};d=e.split(" --\x3e ");c.startTime=ga(d[0]);c.ua=ga(d[1]);for(d=[];a[++g]&&(e=u.trim(a[g]));)d.push(e);c.text=d.join("<br/>");this.fa.push(c)}this.ha=2;this.j("loaded")}; +function ga(a){var c=a.split(":");a=0;var d,e,g;3==c.length?(d=c[0],e=c[1],c=c[2]):(d=0,e=c[0],c=c[1]);c=c.split(/\s+/);c=c.splice(0,1)[0];c=c.split(/\.|,/);g=parseFloat(c[1]);c=c[0];a+=3600*parseFloat(d);a+=60*parseFloat(e);a+=parseFloat(c);g&&(a+=g/1E3);return a} +t.update=function(){if(0<this.fa.length){var a=this.b.currentTime();if(this.Kb===b||a<this.Kb||this.La<=a){var c=this.fa,d=this.b.duration(),e=0,g=l,h=[],k,r,n,s;a>=this.La||this.La===b?s=this.vb!==b?this.vb:0:(g=f,s=this.Cb!==b?this.Cb:c.length-1);for(;;){n=c[s];if(n.ua<=a)e=Math.max(e,n.ua),n.Ha&&(n.Ha=l);else if(a<n.startTime){if(d=Math.min(d,n.startTime),n.Ha&&(n.Ha=l),!g)break}else g?(h.splice(0,0,n),r===b&&(r=s),k=s):(h.push(n),k===b&&(k=s),r=s),d=Math.min(d,n.ua),e=Math.max(e,n.startTime), +n.Ha=f;if(g)if(0===s)break;else s--;else if(s===c.length-1)break;else s++}this.bc=h;this.La=d;this.Kb=e;this.vb=k;this.Cb=r;a=this.bc;c="";d=0;for(e=a.length;d<e;d++)c+='<span class="vjs-tt-cue">'+a[d].text+"</span>";this.a.innerHTML=c;this.j("cuechange")}}};t.reset=function(){this.La=0;this.Kb=this.b.duration();this.Cb=this.vb=0};u.Sb=u.X.extend();u.Sb.prototype.A="captions";u.Yb=u.X.extend();u.Yb.prototype.A="subtitles";u.Tb=u.X.extend();u.Tb.prototype.A="chapters"; +u.Zb=u.c.extend({i:function(a,c,d){u.c.call(this,a,c,d);if(a.g.tracks&&0<a.g.tracks.length){c=this.b;a=a.g.tracks;var e;for(d=0;d<a.length;d++){e=a[d];var g=c,h=e.kind,k=e.label,r=e.language,n=e;e=g.za=g.za||[];n=n||{};n.kind=h;n.label=k;n.language=r;h=u.$(h||"subtitles");g=new window.videojs[h+"Track"](g,n);e.push(g)}}}});u.Zb.prototype.e=function(){return u.c.prototype.e.call(this,"div",{className:"vjs-text-track-display"})}; +u.Y=u.N.extend({i:function(a,c){var d=this.ca=c.track;c.label=d.label();c.selected=d.tb();u.N.call(this,a,c);this.b.d(d.K()+"trackchange",u.bind(this,this.update))}});u.Y.prototype.p=function(){u.N.prototype.p.call(this);X(this.b,this.ca.Q,this.ca.K())};u.Y.prototype.update=function(){this.selected(2==this.ca.mode())};u.ab=u.Y.extend({i:function(a,c){c.track={K:function(){return c.kind},L:a,label:function(){return c.kind+" off"},tb:q(l),mode:q(l)};u.Y.call(this,a,c);this.selected(f)}}); +u.ab.prototype.p=function(){u.Y.prototype.p.call(this);X(this.b,this.ca.Q,this.ca.K())};u.ab.prototype.update=function(){for(var a=W(this.b),c=0,d=a.length,e,g=f;c<d;c++)e=a[c],e.K()==this.ca.K()&&2==e.mode()&&(g=l);this.selected(g)};u.S=u.R.extend({i:function(a,c){u.R.call(this,a,c);1>=this.J.length&&this.C()}});u.S.prototype.sa=function(){var a=[],c;a.push(new u.ab(this.b,{kind:this.A}));for(var d=0;d<W(this.b).length;d++)c=W(this.b)[d],c.K()===this.A&&a.push(new u.Y(this.b,{track:c}));return a}; +u.Ca=u.S.extend({i:function(a,c,d){u.S.call(this,a,c,d);this.a.setAttribute("aria-label","Captions Menu")}});u.Ca.prototype.A="captions";u.Ca.prototype.pa="Captions";u.Ca.prototype.className="vjs-captions-button";u.Ga=u.S.extend({i:function(a,c,d){u.S.call(this,a,c,d);this.a.setAttribute("aria-label","Subtitles Menu")}});u.Ga.prototype.A="subtitles";u.Ga.prototype.pa="Subtitles";u.Ga.prototype.className="vjs-subtitles-button"; +u.Da=u.S.extend({i:function(a,c,d){u.S.call(this,a,c,d);this.a.setAttribute("aria-label","Chapters Menu")}});t=u.Da.prototype;t.A="chapters";t.pa="Chapters";t.className="vjs-chapters-button";t.sa=function(){for(var a=[],c,d=0;d<W(this.b).length;d++)c=W(this.b)[d],c.K()===this.A&&a.push(new u.Y(this.b,{track:c}));return a}; +t.Ja=function(){for(var a=W(this.b),c=0,d=a.length,e,g,h=this.J=[];c<d;c++)if(e=a[c],e.K()==this.A&&e.tb()){if(2>e.readyState()){this.Fd=e;e.d("loaded",u.bind(this,this.Ja));return}g=e;break}a=this.va=new u.la(this.b);a.a.appendChild(u.e("li",{className:"vjs-menu-title",innerHTML:u.$(this.A),wd:-1}));if(g){e=g.fa;for(var k,c=0,d=e.length;c<d;c++)k=e[c],k=new u.Wa(this.b,{track:g,cue:k}),h.push(k),a.Z(k)}0<this.J.length&&this.show();return a}; +u.Wa=u.N.extend({i:function(a,c){var d=this.ca=c.track,e=this.cue=c.cue,g=a.currentTime();c.label=e.text;c.selected=e.startTime<=g&&g<e.ua;u.N.call(this,a,c);d.d("cuechange",u.bind(this,this.update))}});u.Wa.prototype.p=function(){u.N.prototype.p.call(this);this.b.currentTime(this.cue.startTime);this.update(this.cue.startTime)};u.Wa.prototype.update=function(){var a=this.cue,c=this.b.currentTime();this.selected(a.startTime<=c&&c<a.ua)}; +u.k.B(u.Ea.prototype.g.children,{subtitlesButton:{},captionsButton:{},chaptersButton:{}}); +if("undefined"!==typeof window.JSON&&"function"===window.JSON.parse)u.JSON=window.JSON;else{u.JSON={};var Z=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;u.JSON.parse=function(a,c){function d(a,e){var k,r,n=a[e];if(n&&"object"===typeof n)for(k in n)Object.prototype.hasOwnProperty.call(n,k)&&(r=d(n,k),r!==b?n[k]=r:delete n[k]);return c.call(a,e,n)}var e;a=String(a);Z.lastIndex=0;Z.test(a)&&(a=a.replace(Z,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})); +if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return e=eval("("+a+")"),"function"===typeof c?d({"":e},""):e;throw new SyntaxError("JSON.parse(): invalid or malformed JSON data");}} +u.cc=function(){var a,c,d=document.getElementsByTagName("video");if(d&&0<d.length)for(var e=0,g=d.length;e<g;e++)if((c=d[e])&&c.getAttribute)c.player===b&&(a=c.getAttribute("data-setup"),a!==j&&(a=u.JSON.parse(a||"{}"),v(c,a)));else{u.jb();break}else u.Ac||u.jb()};u.jb=function(){setTimeout(u.cc,1)};"complete"===document.readyState?u.Ac=f:u.U(window,"load",function(){u.Ac=f});u.jb();u.ld=function(a,c){u.w.prototype[a]=c};var ha=this;ha.Bd=f;function $(a,c){var d=a.split("."),e=ha;!(d[0]in e)&&e.execScript&&e.execScript("var "+d[0]);for(var g;d.length&&(g=d.shift());)!d.length&&c!==b?e[g]=c:e=e[g]?e[g]:e[g]={}};$("videojs",u);$("_V_",u);$("videojs.options",u.options);$("videojs.players",u.wa);$("videojs.cache",u.qa);$("videojs.Component",u.c);u.c.prototype.player=u.c.prototype.L;u.c.prototype.dispose=u.c.prototype.D;u.c.prototype.createEl=u.c.prototype.e;u.c.prototype.el=u.c.prototype.v;u.c.prototype.addChild=u.c.prototype.Z;u.c.prototype.children=u.c.prototype.children;u.c.prototype.on=u.c.prototype.d;u.c.prototype.off=u.c.prototype.n;u.c.prototype.one=u.c.prototype.U;u.c.prototype.trigger=u.c.prototype.j; +u.c.prototype.triggerReady=u.c.prototype.Ta;u.c.prototype.show=u.c.prototype.show;u.c.prototype.hide=u.c.prototype.C;u.c.prototype.width=u.c.prototype.width;u.c.prototype.height=u.c.prototype.height;u.c.prototype.dimensions=u.c.prototype.Tc;u.c.prototype.ready=u.c.prototype.M;u.c.prototype.addClass=u.c.prototype.m;u.c.prototype.removeClass=u.c.prototype.t;$("videojs.Player",u.w);u.w.prototype.dispose=u.w.prototype.D;u.w.prototype.requestFullScreen=u.w.prototype.xa;u.w.prototype.cancelFullScreen=u.w.prototype.nb; +u.w.prototype.bufferedPercent=u.w.prototype.Ia;u.w.prototype.usingNativeControls=u.w.prototype.Pb;$("videojs.MediaLoader",u.Kc);$("videojs.TextTrackDisplay",u.Zb);$("videojs.ControlBar",u.Ea);$("videojs.Button",u.q);$("videojs.PlayToggle",u.Wb);$("videojs.FullscreenToggle",u.Fa);$("videojs.BigPlayButton",u.Va);$("videojs.LoadingSpinner",u.Ub);$("videojs.CurrentTimeDisplay",u.Xa);$("videojs.DurationDisplay",u.Ya);$("videojs.TimeDivider",u.$b);$("videojs.RemainingTimeDisplay",u.eb); +$("videojs.Slider",u.O);$("videojs.ProgressControl",u.cb);$("videojs.SeekBar",u.Xb);$("videojs.LoadProgressBar",u.$a);$("videojs.PlayProgressBar",u.Vb);$("videojs.SeekHandle",u.fb);$("videojs.VolumeControl",u.hb);$("videojs.VolumeBar",u.gb);$("videojs.VolumeLevel",u.ac);$("videojs.VolumeMenuButton",u.na);$("videojs.VolumeHandle",u.ib);$("videojs.MuteToggle",u.da);$("videojs.PosterImage",u.bb);$("videojs.Menu",u.la);$("videojs.MenuItem",u.N);$("videojs.MenuButton",u.R);u.R.prototype.createItems=u.R.prototype.sa; +u.S.prototype.createItems=u.S.prototype.sa;u.Da.prototype.createItems=u.Da.prototype.sa;$("videojs.SubtitlesButton",u.Ga);$("videojs.CaptionsButton",u.Ca);$("videojs.ChaptersButton",u.Da);$("videojs.MediaTechController",u.r);u.r.prototype.features=u.r.prototype.l;u.r.prototype.l.volumeControl=u.r.prototype.l.zc;u.r.prototype.l.fullscreenResize=u.r.prototype.l.Gd;u.r.prototype.l.progressEvents=u.r.prototype.l.Kd;u.r.prototype.l.timeupdateEvents=u.r.prototype.l.Pd;$("videojs.Html5",u.o); +u.o.Events=u.o.Za;u.o.isSupported=u.o.isSupported;u.o.canPlaySource=u.o.lb;u.o.prototype.setCurrentTime=u.o.prototype.pd;u.o.prototype.setVolume=u.o.prototype.ud;u.o.prototype.setMuted=u.o.prototype.sd;u.o.prototype.setPreload=u.o.prototype.td;u.o.prototype.setAutoplay=u.o.prototype.od;u.o.prototype.setLoop=u.o.prototype.rd;$("videojs.Flash",u.f);u.f.isSupported=u.f.isSupported;u.f.canPlaySource=u.f.lb;u.f.onReady=u.f.onReady;$("videojs.TextTrack",u.X);u.X.prototype.label=u.X.prototype.label; +$("videojs.CaptionsTrack",u.Sb);$("videojs.SubtitlesTrack",u.Yb);$("videojs.ChaptersTrack",u.Tb);$("videojs.autoSetup",u.cc);$("videojs.plugin",u.ld);$("videojs.createTimeRange",u.sb);})(); diff --git a/extlib/video-js/video.min.js b/extlib/video-js/video.min.js deleted file mode 100644 index 1c33af55..00000000 --- a/extlib/video-js/video.min.js +++ /dev/null @@ -1,21 +0,0 @@ -/*! -Video.js - HTML5 Video Player -Version GENERATED_AT_BUILD - -LGPL v3 LICENSE INFO -This file is part of Video.js. Copyright 2011 Zencoder, Inc. - -Video.js is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Video.js 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with Video.js. If not, see <http://www.gnu.org/licenses/>. -*/ -(function(window,undefined){var document=window.document;document.createElement("video");document.createElement("audio");var VideoJS=function(id,addOptions,ready){var tag;if(typeof id=="string"){if(id.indexOf("#")===0){id=id.slice(1)}if(_V_.players[id]){return _V_.players[id]}else{tag=_V_.el(id)}}else{tag=id}if(!tag||!tag.nodeName){throw new TypeError("The element or ID supplied is not valid. (VideoJS)")}return tag.player||new _V_.Player(tag,addOptions,ready)},_V_=VideoJS,CDN_VERSION="GENERATED_CDN_VSN";VideoJS.players={};VideoJS.options={techOrder:["html5","flash"],html5:{},flash:{swf:"http://vjs.zencdn.net/c/video-js.swf"},width:300,height:150,defaultVolume:0,components:{posterImage:{},textTrackDisplay:{},loadingSpinner:{},bigPlayButton:{},controlBar:{}}};if(CDN_VERSION!="GENERATED_CDN_VSN"){_V_.options.flash.swf="http://vjs.zencdn.net/"+CDN_VERSION+"/video-js.swf"}_V_.merge=function(obj1,obj2,safe){if(!obj2){obj2={}}for(var attrname in obj2){if(obj2.hasOwnProperty(attrname)&&(!safe||!obj1.hasOwnProperty(attrname))){obj1[attrname]=obj2[attrname]}}return obj1};_V_.extend=function(obj){this.merge(this,obj,true)};_V_.extend({tech:{},controlSets:{},isIE:function(){return !+"\v1"},isFF:function(){return !!_V_.ua.match("Firefox")},isIPad:function(){return navigator.userAgent.match(/iPad/i)!==null},isIPhone:function(){return navigator.userAgent.match(/iPhone/i)!==null},isIOS:function(){return VideoJS.isIPhone()||VideoJS.isIPad()},iOSVersion:function(){var match=navigator.userAgent.match(/OS (\d+)_/i);if(match&&match[1]){return match[1]}},isAndroid:function(){return navigator.userAgent.match(/Android.*AppleWebKit/i)!==null},androidVersion:function(){var match=navigator.userAgent.match(/Android (\d+)\./i);if(match&&match[1]){return match[1]}},testVid:document.createElement("video"),ua:navigator.userAgent,support:{},each:function(arr,fn){if(!arr||arr.length===0){return}for(var i=0,j=arr.length;i<j;i++){fn.call(this,arr[i],i)}},eachProp:function(obj,fn){if(!obj){return}for(var name in obj){if(obj.hasOwnProperty(name)){fn.call(this,name,obj[name])}}},el:function(id){return document.getElementById(id)},createElement:function(tagName,attributes){var el=document.createElement(tagName),attrname;for(attrname in attributes){if(attributes.hasOwnProperty(attrname)){if(attrname.indexOf("-")!==-1){el.setAttribute(attrname,attributes[attrname])}else{el[attrname]=attributes[attrname]}}}return el},insertFirst:function(node,parent){if(parent.firstChild){parent.insertBefore(node,parent.firstChild)}else{parent.appendChild(node)}},addClass:function(element,classToAdd){if((" "+element.className+" ").indexOf(" "+classToAdd+" ")==-1){element.className=element.className===""?classToAdd:element.className+" "+classToAdd}},removeClass:function(element,classToRemove){if(element.className.indexOf(classToRemove)==-1){return}var classNames=element.className.split(" ");classNames.splice(classNames.indexOf(classToRemove),1);element.className=classNames.join(" ")},remove:function(item,array){if(!array){return}var i=array.indexOf(item);if(i!=-1){return array.splice(i,1)}},blockTextSelection:function(){document.body.focus();document.onselectstart=function(){return false}},unblockTextSelection:function(){document.onselectstart=function(){return true}},formatTime:function(seconds,guide){guide=guide||seconds;var s=Math.floor(seconds%60),m=Math.floor(seconds/60%60),h=Math.floor(seconds/3600),gm=Math.floor(guide/60%60),gh=Math.floor(guide/3600);h=(h>0||gh>0)?h+":":"";m=(((h||gm>=10)&&m<10)?"0"+m:m)+":";s=(s<10)?"0"+s:s;return h+m+s},uc:function(string){return string.charAt(0).toUpperCase()+string.slice(1)},getRelativePosition:function(x,relativeElement){return Math.max(0,Math.min(1,(x-_V_.findPosX(relativeElement))/relativeElement.offsetWidth))},getComputedStyleValue:function(element,style){return window.getComputedStyle(element,null).getPropertyValue(style)},trim:function(string){return string.toString().replace(/^\s+/,"").replace(/\s+$/,"")},round:function(num,dec){if(!dec){dec=0}return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec)},isEmpty:function(object){for(var prop in object){return false}return true},createTimeRange:function(start,end){return{length:1,start:function(){return start},end:function(){return end}}},cache:{},guid:1,expando:"vdata"+(new Date).getTime(),getData:function(elem){var id=elem[_V_.expando];if(!id){id=elem[_V_.expando]=_V_.guid++;_V_.cache[id]={}}return _V_.cache[id]},removeData:function(elem){var id=elem[_V_.expando];if(!id){return}delete _V_.cache[id];try{delete elem[_V_.expando]}catch(e){if(elem.removeAttribute){elem.removeAttribute(_V_.expando)}else{elem[_V_.expando]=null}}},proxy:function(context,fn,uid){if(!fn.guid){fn.guid=_V_.guid++}var ret=function(){return fn.apply(context,arguments)};ret.guid=(uid)?uid+"_"+fn.guid:fn.guid;return ret},get:function(url,onSuccess,onError){var local=(url.indexOf("file:")==0||(window.location.href.indexOf("file:")==0&&url.indexOf("http:")==-1));if(typeof XMLHttpRequest=="undefined"){XMLHttpRequest=function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(f){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(g){}throw new Error("This browser does not support XMLHttpRequest.")}}var request=new XMLHttpRequest();try{request.open("GET",url)}catch(e){_V_.log("VideoJS XMLHttpRequest (open)",e);return false}request.onreadystatechange=_V_.proxy(this,function(){if(request.readyState==4){if(request.status==200||local&&request.status==0){onSuccess(request.responseText)}else{if(onError){onError()}}}});try{request.send()}catch(e){_V_.log("VideoJS XMLHttpRequest (send)",e);if(onError){onError(e)}}},setLocalStorage:function(key,value){var localStorage=window.localStorage||false;if(!localStorage){return}try{localStorage[key]=value}catch(e){if(e.code==22||e.code==1014){_V_.log("LocalStorage Full (VideoJS)",e)}else{_V_.log("LocalStorage Error (VideoJS)",e)}}},getAbsoluteURL:function(url){if(!url.match(/^https?:\/\//)){url=_V_.createElement("div",{innerHTML:'<a href="'+url+'">x</a>'}).firstChild.href}return url}});_V_.log=function(){_V_.log.history=_V_.log.history||[];_V_.log.history.push(arguments);if(window.console){arguments.callee=arguments.callee.caller;var newarr=[].slice.call(arguments);(typeof console.log==="object"?_V_.log.apply.call(console.log,console,newarr):console.log.apply(console,newarr))}};(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try{console.log();return window.console}catch(err){return window.console={}}})());if("getBoundingClientRect" in document.documentElement){_V_.findPosX=function(el){var box;try{box=el.getBoundingClientRect()}catch(e){}if(!box){return 0}var docEl=document.documentElement,body=document.body,clientLeft=docEl.clientLeft||body.clientLeft||0,scrollLeft=window.pageXOffset||body.scrollLeft,left=box.left+scrollLeft-clientLeft;return left}}else{_V_.findPosX=function(el){var curleft=el.offsetLeft;while(el=obj.offsetParent){if(el.className.indexOf("video-js")==-1){}else{}curleft+=el.offsetLeft}return curleft}}if(!Array.prototype.indexOf){Array.prototype.indexOf=function(searchElement){if(this===void 0||this===null){throw new TypeError()}var t=Object(this);var len=t.length>>>0;if(len===0){return -1}var n=0;if(arguments.length>0){n=Number(arguments[1]);if(n!==n){n=0}else{if(n!==0&&n!==(1/0)&&n!==-(1/0)){n=(n>0||-1)*Math.floor(Math.abs(n))}}}if(n>=len){return -1}var k=n>=0?n:Math.max(len-Math.abs(n),0);for(;k<len;k++){if(k in t&&t[k]===searchElement){return k}}return -1}}var JSON;if(!JSON){JSON={}}(function(){var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());_V_.extend({addEvent:function(elem,type,fn){var data=_V_.getData(elem),handlers;if(data&&!data.handler){data.handler=function(event){event=_V_.fixEvent(event);var handlers=_V_.getData(elem).events[event.type];if(handlers){var handlersCopy=[];_V_.each(handlers,function(handler,i){handlersCopy[i]=handler});for(var i=0,l=handlersCopy.length;i<l;i++){handlersCopy[i].call(elem,event)}}}}if(!data.events){data.events={}}handlers=data.events[type];if(!handlers){handlers=data.events[type]=[];if(document.addEventListener){elem.addEventListener(type,data.handler,false)}else{if(document.attachEvent){elem.attachEvent("on"+type,data.handler)}}}if(!fn.guid){fn.guid=_V_.guid++}handlers.push(fn)},removeEvent:function(elem,type,fn){var data=_V_.getData(elem),handlers;if(!data.events){return}if(!type){for(type in data.events){_V_.cleanUpEvents(elem,type)}return}handlers=data.events[type];if(!handlers){return}if(fn&&fn.guid){for(var i=0;i<handlers.length;i++){if(handlers[i].guid===fn.guid){handlers.splice(i--,1)}}}_V_.cleanUpEvents(elem,type)},cleanUpEvents:function(elem,type){var data=_V_.getData(elem);if(data.events[type].length===0){delete data.events[type];if(document.removeEventListener){elem.removeEventListener(type,data.handler,false)}else{if(document.detachEvent){elem.detachEvent("on"+type,data.handler)}}}if(_V_.isEmpty(data.events)){delete data.events;delete data.handler}if(_V_.isEmpty(data)){_V_.removeData(elem)}},fixEvent:function(event){if(event[_V_.expando]){return event}var originalEvent=event;event=new _V_.Event(originalEvent);for(var i=_V_.Event.props.length,prop;i;){prop=_V_.Event.props[--i];event[prop]=originalEvent[prop]}if(!event.target){event.target=event.srcElement||document}if(event.target.nodeType===3){event.target=event.target.parentNode}if(!event.relatedTarget&&event.fromElement){event.relatedTarget=event.fromElement===event.target?event.toElement:event.fromElement}if(event.pageX==null&&event.clientX!=null){var eventDocument=event.target.ownerDocument||document,doc=eventDocument.documentElement,body=eventDocument.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc&&doc.clientLeft||body&&body.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc&&doc.clientTop||body&&body.clientTop||0)}if(event.which==null&&(event.charCode!=null||event.keyCode!=null)){event.which=event.charCode!=null?event.charCode:event.keyCode}if(!event.metaKey&&event.ctrlKey){event.metaKey=event.ctrlKey}if(!event.which&&event.button!==undefined){event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)))}return event},triggerEvent:function(elem,event){var data=_V_.getData(elem),parent=elem.parentNode||elem.ownerDocument,type=event.type||event,handler;if(data){handler=data.handler}event=typeof event==="object"?event[_V_.expando]?event:new _V_.Event(type,event):new _V_.Event(type);event.type=type;if(handler){handler.call(elem,event)}event.result=undefined;event.target=elem},one:function(elem,type,fn){_V_.addEvent(elem,type,function(){_V_.removeEvent(elem,type,arguments.callee);fn.apply(this,arguments)})}});_V_.Event=function(src,props){if(src&&src.type){this.originalEvent=src;this.type=src.type;this.isDefaultPrevented=(src.defaultPrevented||src.returnValue===false||src.getPreventDefault&&src.getPreventDefault())?returnTrue:returnFalse}else{this.type=src}if(props){_V_.merge(this,props)}this.timeStamp=(new Date).getTime();this[_V_.expando]=true};_V_.Event.prototype={preventDefault:function(){this.isDefaultPrevented=returnTrue;var e=this.originalEvent;if(!e){return}if(e.preventDefault){e.preventDefault()}else{e.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=returnTrue;var e=this.originalEvent;if(!e){return}if(e.stopPropagation){e.stopPropagation()}e.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=returnTrue;this.stopPropagation()},isDefaultPrevented:returnFalse,isPropagationStopped:returnFalse,isImmediatePropagationStopped:returnFalse};_V_.Event.props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" ");function returnTrue(){return true}function returnFalse(){return false}(function(){var initializing=false,fnTest=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;_V_.Class=function(){};_V_.Class.extend=function(prop){var _super=this.prototype;initializing=true;var prototype=new this();initializing=false;for(var name in prop){prototype[name]=typeof prop[name]=="function"&&typeof _super[name]=="function"&&fnTest.test(prop[name])?(function(name,fn){return function(){var tmp=this._super;this._super=_super[name];var ret=fn.apply(this,arguments);this._super=tmp;return ret}})(name,prop[name]):prop[name]}function Class(){if(!initializing&&this.init){return this.init.apply(this,arguments)}else{if(!initializing){return arguments.callee.prototype.init()}}}Class.prototype=prototype;Class.constructor=Class;Class.extend=arguments.callee;return Class}})();_V_.Component=_V_.Class.extend({init:function(player,options){this.player=player;options=this.options=_V_.merge(this.options||{},options);if(options.el){this.el=options.el}else{this.el=this.createElement()}this.initComponents()},destroy:function(){},createElement:function(type,attrs){return _V_.createElement(type||"div",attrs)},buildCSSClass:function(){return""},initComponents:function(){var options=this.options;if(options&&options.components){this.eachProp(options.components,function(name,opts){var tempAdd=this.proxy(function(){this[name]=this.addComponent(name,opts)});if(opts.loadEvent){this.one(opts.loadEvent,tempAdd)}else{tempAdd()}})}},addComponent:function(name,options){var component,componentClass;if(typeof name=="string"){options=options||{};componentClass=options.componentClass||_V_.uc(name);component=new _V_[componentClass](this.player||this,options)}else{component=name}this.el.appendChild(component.el);return component},removeComponent:function(component){this.el.removeChild(component.el)},show:function(){this.el.style.display="block"},hide:function(){this.el.style.display="none"},fadeIn:function(){this.removeClass("vjs-fade-out");this.addClass("vjs-fade-in")},fadeOut:function(){this.removeClass("vjs-fade-in");this.addClass("vjs-fade-out")},lockShowing:function(){var style=this.el.style;style.display="block";style.opacity=1;style.visiblity="visible"},unlockShowing:function(){var style=this.el.style;style.display="";style.opacity="";style.visiblity=""},addClass:function(classToAdd){_V_.addClass(this.el,classToAdd)},removeClass:function(classToRemove){_V_.removeClass(this.el,classToRemove)},addEvent:function(type,fn,uid){return _V_.addEvent(this.el,type,_V_.proxy(this,fn))},removeEvent:function(type,fn){return _V_.removeEvent(this.el,type,fn)},triggerEvent:function(type,e){return _V_.triggerEvent(this.el,type,e)},one:function(type,fn){_V_.one(this.el,type,_V_.proxy(this,fn))},ready:function(fn){if(!fn){return this}if(this.isReady){fn.call(this)}else{if(this.readyQueue===undefined){this.readyQueue=[]}this.readyQueue.push(fn)}return this},triggerReady:function(){this.isReady=true;if(this.readyQueue&&this.readyQueue.length>0){this.each(this.readyQueue,function(fn){fn.call(this)});this.readyQueue=[];this.triggerEvent("ready")}},each:function(arr,fn){_V_.each.call(this,arr,fn)},eachProp:function(obj,fn){_V_.eachProp.call(this,obj,fn)},extend:function(obj){_V_.merge(this,obj)},proxy:function(fn,uid){return _V_.proxy(this,fn,uid)}});_V_.Player=_V_.Component.extend({init:function(tag,addOptions,ready){this.tag=tag;var el=this.el=_V_.createElement("div"),options=this.options={};_V_.merge(options,_V_.options);_V_.merge(options,this.getVideoTagSettings());_V_.merge(options,addOptions);this.ready(ready);tag.removeAttribute("controls");tag.removeAttribute("poster");tag.player=el.player=this;tag.parentNode.insertBefore(el,tag);el.appendChild(tag);this.id=el.id=tag.id;el.className=tag.className;tag.id+="_html5_api";tag.className="vjs-tech";_V_.players[el.id]=this;el.setAttribute("width",options.width);el.setAttribute("height",options.height);el.style.width=options.width+"px";el.style.height=options.height+"px";tag.removeAttribute("width");tag.removeAttribute("height");if(tag.hasChildNodes()){for(var i=0,j=tag.childNodes;i<j.length;i++){if(j[i].nodeName=="SOURCE"||j[i].nodeName=="TRACK"){tag.removeChild(j[i])}}}this.values={};this.addClass("vjs-paused");this.addEvent("ended",this.onEnded);this.addEvent("play",this.onPlay);this.addEvent("pause",this.onPause);this.addEvent("progress",this.onProgress);this.addEvent("error",this.onError);if(options.controls){this.ready(function(){this.initComponents()})}this.textTracks=[];if(options.tracks&&options.tracks.length>0){this.addTextTracks(options.tracks)}if(!options.sources||options.sources.length==0){for(var i=0,j=options.techOrder;i<j.length;i++){var techName=j[i],tech=_V_[techName];if(tech.isSupported()){this.loadTech(techName);break}}}else{this.src(options.sources)}},values:{},destroy:function(){this.stopTrackingProgress();this.stopTrackingCurrentTime();_V_.players[this.id]=null;delete _V_.players[this.id];this.tech.destroy();this.el.parentNode.removeChild(this.el)},createElement:function(type,options){},getVideoTagSettings:function(){var options={sources:[],tracks:[]},tag=this.tag,getAttribute="getAttribute";options.src=tag[getAttribute]("src");options.controls=tag[getAttribute]("controls")!==null;options.poster=tag[getAttribute]("poster");options.preload=tag[getAttribute]("preload");options.autoplay=tag[getAttribute]("autoplay")!==null;options.loop=tag[getAttribute]("loop")!==null;options.muted=tag[getAttribute]("muted")!==null;if(this.tag.hasChildNodes()){for(var c,i=0,j=this.tag.childNodes;i<j.length;i++){c=j[i];if(c.nodeName=="SOURCE"){options.sources.push({src:c[getAttribute]("src"),type:c[getAttribute]("type"),media:c[getAttribute]("media"),title:c[getAttribute]("title")})}if(c.nodeName=="TRACK"){options.tracks.push({src:c[getAttribute]("src"),kind:c[getAttribute]("kind"),srclang:c[getAttribute]("srclang"),label:c[getAttribute]("label"),"default":c[getAttribute]("default")!==null,title:c[getAttribute]("title")})}}}return options},loadTech:function(techName,source){if(this.tech){this.unloadTech()}else{if(techName!="html5"&&this.tag){this.el.removeChild(this.tag);this.tag=false}}this.techName=techName;this.isReady=false;var techReady=function(){this.player.triggerReady();if(!this.support.progressEvent){this.player.manualProgressOn()}if(!this.support.timeupdateEvent){this.player.manualTimeUpdatesOn()}};var techOptions=_V_.merge({source:source,parentEl:this.el},this.options[techName]);if(source){if(source.src==this.values.src&&this.values.currentTime>0){techOptions.startTime=this.values.currentTime}this.values.src=source.src}this.tech=new _V_[techName](this,techOptions);this.tech.ready(techReady)},unloadTech:function(){this.tech.destroy();if(this.manualProgress){this.manualProgressOff()}if(this.manualTimeUpdates){this.manualTimeUpdatesOff()}this.tech=false},manualProgressOn:function(){this.manualProgress=true;this.trackProgress();this.tech.addEvent("progress",function(){this.removeEvent("progress",arguments.callee);this.support.progressEvent=true;this.player.manualProgressOff()})},manualProgressOff:function(){this.manualProgress=false;this.stopTrackingProgress()},trackProgress:function(){this.progressInterval=setInterval(_V_.proxy(this,function(){if(this.values.bufferEnd<this.buffered().end(0)){this.triggerEvent("progress")}else{if(this.bufferedPercent()==1){this.stopTrackingProgress();this.triggerEvent("progress")}}}),500)},stopTrackingProgress:function(){clearInterval(this.progressInterval)},manualTimeUpdatesOn:function(){this.manualTimeUpdates=true;this.addEvent("play",this.trackCurrentTime);this.addEvent("pause",this.stopTrackingCurrentTime);this.tech.addEvent("timeupdate",function(){this.removeEvent("timeupdate",arguments.callee);this.support.timeupdateEvent=true;this.player.manualTimeUpdatesOff()})},manualTimeUpdatesOff:function(){this.manualTimeUpdates=false;this.stopTrackingCurrentTime();this.removeEvent("play",this.trackCurrentTime);this.removeEvent("pause",this.stopTrackingCurrentTime)},trackCurrentTime:function(){if(this.currentTimeInterval){this.stopTrackingCurrentTime()}this.currentTimeInterval=setInterval(_V_.proxy(this,function(){this.triggerEvent("timeupdate")}),250)},stopTrackingCurrentTime:function(){clearInterval(this.currentTimeInterval)},onEnded:function(){if(this.options.loop){this.currentTime(0);this.play()}else{this.pause();this.currentTime(0);this.pause()}},onPlay:function(){_V_.removeClass(this.el,"vjs-paused");_V_.addClass(this.el,"vjs-playing")},onPause:function(){_V_.removeClass(this.el,"vjs-playing");_V_.addClass(this.el,"vjs-paused")},onProgress:function(){if(this.bufferedPercent()==1){this.triggerEvent("loadedalldata")}},onError:function(e){_V_.log("Video Error",e)},techCall:function(method,arg){if(!this.tech.isReady){this.tech.ready(function(){this[method](arg)})}else{try{this.tech[method](arg)}catch(e){_V_.log(e)}}},techGet:function(method){if(this.tech.isReady){try{return this.tech[method]()}catch(e){if(this.tech[method]===undefined){_V_.log("Video.js: "+method+" method not defined for "+this.techName+" playback technology.",e)}else{if(e.name=="TypeError"){_V_.log("Video.js: "+method+" unavailable on "+this.techName+" playback technology element.",e);this.tech.isReady=false}else{_V_.log(e)}}}}return},play:function(){this.techCall("play");return this},pause:function(){this.techCall("pause");return this},paused:function(){return(this.techGet("paused")===false)?false:true},currentTime:function(seconds){if(seconds!==undefined){this.values.lastSetCurrentTime=seconds;this.techCall("setCurrentTime",seconds);if(this.manualTimeUpdates){this.triggerEvent("timeupdate")}return this}return this.values.currentTime=(this.techGet("currentTime")||0)},duration:function(){return parseFloat(this.techGet("duration"))},remainingTime:function(){return this.duration()-this.currentTime()},buffered:function(){var buffered=this.techGet("buffered"),start=0,end=this.values.bufferEnd=this.values.bufferEnd||0,timeRange;if(buffered&&buffered.length>0&&buffered.end(0)!==end){end=buffered.end(0);this.values.bufferEnd=end}return _V_.createTimeRange(start,end)},bufferedPercent:function(){return(this.duration())?this.buffered().end(0)/this.duration():0},volume:function(percentAsDecimal){var vol;if(percentAsDecimal!==undefined){vol=Math.max(0,Math.min(1,parseFloat(percentAsDecimal)));this.values.volume=vol;this.techCall("setVolume",vol);_V_.setLocalStorage("volume",vol);return this}vol=parseFloat(this.techGet("volume"));return(isNaN(vol))?1:vol},muted:function(muted){if(muted!==undefined){this.techCall("setMuted",muted);return this}return this.techGet("muted")||false},width:function(width,skipListeners){if(width!==undefined){this.el.width=width;this.el.style.width=width+"px";if(!skipListeners){this.triggerEvent("resize")}return this}return parseInt(this.el.getAttribute("width"))},height:function(height){if(height!==undefined){this.el.height=height;this.el.style.height=height+"px";this.triggerEvent("resize");return this}return parseInt(this.el.getAttribute("height"))},size:function(width,height){return this.width(width,true).height(height)},supportsFullScreen:function(){return this.techGet("supportsFullScreen")||false},requestFullScreen:function(){var requestFullScreen=_V_.support.requestFullScreen;this.isFullScreen=true;if(requestFullScreen){_V_.addEvent(document,requestFullScreen.eventName,this.proxy(function(){this.isFullScreen=document[requestFullScreen.isFullScreen];if(this.isFullScreen==false){_V_.removeEvent(document,requestFullScreen.eventName,arguments.callee)}this.triggerEvent("fullscreenchange")}));if(this.tech.support.fullscreenResize===false&&this.options.flash.iFrameMode!=true){this.pause();this.unloadTech();_V_.addEvent(document,requestFullScreen.eventName,this.proxy(function(){_V_.removeEvent(document,requestFullScreen.eventName,arguments.callee);this.loadTech(this.techName,{src:this.values.src})}));this.el[requestFullScreen.requestFn]()}else{this.el[requestFullScreen.requestFn]()}}else{if(this.tech.supportsFullScreen()){this.triggerEvent("fullscreenchange");this.techCall("enterFullScreen")}else{this.triggerEvent("fullscreenchange");this.enterFullWindow()}}return this},cancelFullScreen:function(){var requestFullScreen=_V_.support.requestFullScreen;this.isFullScreen=false;if(requestFullScreen){if(this.tech.support.fullscreenResize===false&&this.options.flash.iFrameMode!=true){this.pause();this.unloadTech();_V_.addEvent(document,requestFullScreen.eventName,this.proxy(function(){_V_.removeEvent(document,requestFullScreen.eventName,arguments.callee);this.loadTech(this.techName,{src:this.values.src})}));document[requestFullScreen.cancelFn]()}else{document[requestFullScreen.cancelFn]()}}else{if(this.tech.supportsFullScreen()){this.techCall("exitFullScreen");this.triggerEvent("fullscreenchange")}else{this.exitFullWindow();this.triggerEvent("fullscreenchange")}}return this},enterFullWindow:function(){this.isFullWindow=true;this.docOrigOverflow=document.documentElement.style.overflow;_V_.addEvent(document,"keydown",_V_.proxy(this,this.fullWindowOnEscKey));document.documentElement.style.overflow="hidden";_V_.addClass(document.body,"vjs-full-window");_V_.addClass(this.el,"vjs-fullscreen");this.triggerEvent("enterFullWindow")},fullWindowOnEscKey:function(event){if(event.keyCode==27){if(this.isFullScreen==true){this.cancelFullScreen()}else{this.exitFullWindow()}}},exitFullWindow:function(){this.isFullWindow=false;_V_.removeEvent(document,"keydown",this.fullWindowOnEscKey);document.documentElement.style.overflow=this.docOrigOverflow;_V_.removeClass(document.body,"vjs-full-window");_V_.removeClass(this.el,"vjs-fullscreen");this.triggerEvent("exitFullWindow")},selectSource:function(sources){for(var i=0,j=this.options.techOrder;i<j.length;i++){var techName=j[i],tech=_V_[techName];if(tech.isSupported()){for(var a=0,b=sources;a<b.length;a++){var source=b[a];if(tech.canPlaySource.call(this,source)){return{source:source,tech:techName}}}}}return false},src:function(source){if(source instanceof Array){var sourceTech=this.selectSource(source),source,techName;if(sourceTech){source=sourceTech.source;techName=sourceTech.tech;if(techName==this.techName){this.src(source)}else{this.loadTech(techName,source)}}else{_V_.log("No compatible source and playback technology were found.")}}else{if(source instanceof Object){if(_V_[this.techName].canPlaySource(source)){this.src(source.src)}else{this.src([source])}}else{this.values.src=source;if(!this.isReady){this.ready(function(){this.src(source)})}else{this.techCall("src",source);if(this.options.preload=="auto"){this.load()}if(this.options.autoplay){this.play()}}}}return this},load:function(){this.techCall("load");return this},currentSrc:function(){return this.techGet("currentSrc")||this.values.src||""},preload:function(value){if(value!==undefined){this.techCall("setPreload",value);this.options.preload=value;return this}return this.techGet("preload")},autoplay:function(value){if(value!==undefined){this.techCall("setAutoplay",value);this.options.autoplay=value;return this}return this.techGet("autoplay",value)},loop:function(value){if(value!==undefined){this.techCall("setLoop",value);this.options.loop=value;return this}return this.techGet("loop")},controls:function(){return this.options.controls},poster:function(){return this.techGet("poster")},error:function(){return this.techGet("error")},ended:function(){return this.techGet("ended")}});(function(){var requestFn,cancelFn,eventName,isFullScreen,playerProto=_V_.Player.prototype;if(document.cancelFullscreen!==undefined){requestFn="requestFullscreen";cancelFn="exitFullscreen";eventName="fullscreenchange";isFullScreen="fullScreen"}else{_V_.each(["moz","webkit"],function(prefix){if((prefix!="moz"||document.mozFullScreenEnabled)&&document[prefix+"CancelFullScreen"]!==undefined){requestFn=prefix+"RequestFullScreen";cancelFn=prefix+"CancelFullScreen";eventName=prefix+"fullscreenchange";if(prefix=="webkit"){isFullScreen=prefix+"IsFullScreen"}else{isFullScreen=prefix+"FullScreen"}}})}if(requestFn){_V_.support.requestFullScreen={requestFn:requestFn,cancelFn:cancelFn,eventName:eventName,isFullScreen:isFullScreen}}})();_V_.PlaybackTech=_V_.Component.extend({init:function(player,options){},onClick:function(){if(this.player.options.controls){_V_.PlayToggle.prototype.onClick.call(this)}}});_V_.apiMethods="play,pause,paused,currentTime,setCurrentTime,duration,buffered,volume,setVolume,muted,setMuted,width,height,supportsFullScreen,enterFullScreen,src,load,currentSrc,preload,setPreload,autoplay,setAutoplay,loop,setLoop,error,networkState,readyState,seeking,initialTime,startOffsetTime,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks,defaultPlaybackRate,playbackRate,mediaGroup,controller,controls,defaultMuted".split(",");_V_.each(_V_.apiMethods,function(methodName){_V_.PlaybackTech.prototype[methodName]=function(){throw new Error("The '"+methodName+"' method is not available on the playback technology's API")}});_V_.html5=_V_.PlaybackTech.extend({init:function(player,options,ready){this.player=player;this.el=this.createElement();this.ready(ready);this.addEvent("click",this.proxy(this.onClick));var source=options.source;if(source&&this.el.currentSrc==source.src){player.triggerEvent("loadstart")}else{if(source){this.el.src=source.src}}player.ready(function(){if(this.options.autoplay&&this.paused()){this.tag.poster=null;this.play()}});this.setupTriggers();this.triggerReady()},destroy:function(){this.player.tag=false;this.removeTriggers();this.el.parentNode.removeChild(this.el)},createElement:function(){var html5=_V_.html5,player=this.player,el=player.tag,newEl;if(!el||this.support.movingElementInDOM===false){if(el){player.el.removeChild(el)}newEl=_V_.createElement("video",{id:el.id||player.el.id+"_html5_api",className:el.className||"vjs-tech"});el=newEl;_V_.insertFirst(el,player.el)}_V_.each(["autoplay","preload","loop","muted"],function(attr){if(player.options[attr]!==null){el[attr]=player.options[attr]}},this);return el},setupTriggers:function(){_V_.each.call(this,_V_.html5.events,function(type){_V_.addEvent(this.el,type,_V_.proxy(this.player,this.eventHandler))})},removeTriggers:function(){_V_.each.call(this,_V_.html5.events,function(type){_V_.removeEvent(this.el,type,_V_.proxy(this.player,this.eventHandler))})},eventHandler:function(e){e.stopPropagation();this.triggerEvent(e)},play:function(){this.el.play()},pause:function(){this.el.pause()},paused:function(){return this.el.paused},currentTime:function(){return this.el.currentTime},setCurrentTime:function(seconds){try{this.el.currentTime=seconds}catch(e){_V_.log(e,"Video isn't ready. (VideoJS)")}},duration:function(){return this.el.duration||0},buffered:function(){return this.el.buffered},volume:function(){return this.el.volume},setVolume:function(percentAsDecimal){this.el.volume=percentAsDecimal},muted:function(){return this.el.muted},setMuted:function(muted){this.el.muted=muted},width:function(){return this.el.offsetWidth},height:function(){return this.el.offsetHeight},supportsFullScreen:function(){if(typeof this.el.webkitEnterFullScreen=="function"){if(!navigator.userAgent.match("Chrome")&&!navigator.userAgent.match("Mac OS X 10.5")){return true}}return false},enterFullScreen:function(){try{this.el.webkitEnterFullScreen()}catch(e){if(e.code==11){_V_.log("VideoJS: Video not ready.")}}},src:function(src){this.el.src=src},load:function(){this.el.load()},currentSrc:function(){return this.el.currentSrc},preload:function(){return this.el.preload},setPreload:function(val){this.el.preload=val},autoplay:function(){return this.el.autoplay},setAutoplay:function(val){this.el.autoplay=val},loop:function(){return this.el.loop},setLoop:function(val){this.el.loop=val},error:function(){return this.el.error},seeking:function(){return this.el.seeking},ended:function(){return this.el.ended},controls:function(){return this.player.options.controls},defaultMuted:function(){return this.el.defaultMuted}});_V_.html5.isSupported=function(){return !!document.createElement("video").canPlayType};_V_.html5.canPlaySource=function(srcObj){return !!document.createElement("video").canPlayType(srcObj.type)};_V_.html5.events="loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange".split(",");_V_.html5.prototype.support={fullscreen:(typeof _V_.testVid.webkitEnterFullScreen!==undefined)?(!_V_.ua.match("Chrome")&&!_V_.ua.match("Mac OS X 10.5")?true:false):false,movingElementInDOM:!_V_.isIOS()};if(_V_.isAndroid()){if(_V_.androidVersion()<3){document.createElement("video").constructor.prototype.canPlayType=function(type){return(type&&type.toLowerCase().indexOf("video/mp4")!=-1)?"maybe":""}}}_V_.flash=_V_.PlaybackTech.extend({init:function(player,options){this.player=player;var source=options.source,parentEl=options.parentEl,placeHolder=this.el=_V_.createElement("div",{id:parentEl.id+"_temp_flash"}),objId=player.el.id+"_flash_api",playerOptions=player.options,flashVars=_V_.merge({readyFunction:"_V_.flash.onReady",eventProxyFunction:"_V_.flash.onEvent",errorEventProxyFunction:"_V_.flash.onError",autoplay:playerOptions.autoplay,preload:playerOptions.preload,loop:playerOptions.loop,muted:playerOptions.muted},options.flashVars),params=_V_.merge({wmode:"opaque",bgcolor:"#000000"},options.params),attributes=_V_.merge({id:objId,name:objId,"class":"vjs-tech"},options.attributes);if(source){flashVars.src=encodeURIComponent(_V_.getAbsoluteURL(source.src))}_V_.insertFirst(placeHolder,parentEl);if(options.startTime){this.ready(function(){this.load();this.play();this.currentTime(options.startTime)})}if(options.iFrameMode==true&&!_V_.isFF){var iFrm=_V_.createElement("iframe",{id:objId+"_iframe",name:objId+"_iframe",className:"vjs-tech",scrolling:"no",marginWidth:0,marginHeight:0,frameBorder:0});flashVars.readyFunction="ready";flashVars.eventProxyFunction="events";flashVars.errorEventProxyFunction="errors";_V_.addEvent(iFrm,"load",_V_.proxy(this,function(){var iDoc,objTag,swfLoc,iWin=iFrm.contentWindow,varString="";iDoc=iFrm.contentDocument?iFrm.contentDocument:iFrm.contentWindow.document;iDoc.write(_V_.flash.getEmbedCode(options.swf,flashVars,params,attributes));iWin.player=this.player;iWin.ready=_V_.proxy(this.player,function(currSwf){var el=iDoc.getElementById(currSwf),player=this,tech=player.tech;tech.el=el;_V_.addEvent(el,"click",tech.proxy(tech.onClick));_V_.flash.checkReady(tech)});iWin.events=_V_.proxy(this.player,function(swfID,eventName,other){var player=this;if(player&&player.techName=="flash"){player.triggerEvent(eventName)}});iWin.errors=_V_.proxy(this.player,function(swfID,eventName){_V_.log("Flash Error",eventName)})}));placeHolder.parentNode.replaceChild(iFrm,placeHolder)}else{_V_.flash.embed(options.swf,placeHolder,flashVars,params,attributes)}},destroy:function(){this.el.parentNode.removeChild(this.el)},play:function(){this.el.vjs_play()},pause:function(){this.el.vjs_pause()},src:function(src){src=_V_.getAbsoluteURL(src);this.el.vjs_src(src);if(this.player.autoplay()){var tech=this;setTimeout(function(){tech.play()},0)}},load:function(){this.el.vjs_load()},poster:function(){this.el.vjs_getProperty("poster")},buffered:function(){return _V_.createTimeRange(0,this.el.vjs_getProperty("buffered"))},supportsFullScreen:function(){return false},enterFullScreen:function(){return false}});(function(){var api=_V_.flash.prototype,readWrite="preload,currentTime,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted".split(","),readOnly="error,currentSrc,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks".split(","),callOnly="load,play,pause".split(",");createSetter=function(attr){var attrUpper=attr.charAt(0).toUpperCase()+attr.slice(1);api["set"+attrUpper]=function(val){return this.el.vjs_setProperty(attr,val)}},createGetter=function(attr){api[attr]=function(){return this.el.vjs_getProperty(attr)}};_V_.each(readWrite,function(attr){createGetter(attr);createSetter(attr)});_V_.each(readOnly,function(attr){createGetter(attr)})})();_V_.flash.isSupported=function(){return _V_.flash.version()[0]>=10};_V_.flash.canPlaySource=function(srcObj){if(srcObj.type in _V_.flash.prototype.support.formats){return"maybe"}};_V_.flash.prototype.support={formats:{"video/flv":"FLV","video/x-flv":"FLV","video/mp4":"MP4","video/m4v":"MP4"},progressEvent:false,timeupdateEvent:false,fullscreenResize:false,parentResize:!(_V_.ua.match("Firefox"))};_V_.flash.onReady=function(currSwf){var el=_V_.el(currSwf);var player=el.player||el.parentNode.player,tech=player.tech;el.player=player;tech.el=el;tech.addEvent("click",tech.onClick);_V_.flash.checkReady(tech)};_V_.flash.checkReady=function(tech){if(tech.el.vjs_getProperty){tech.triggerReady()}else{setTimeout(function(){_V_.flash.checkReady(tech)},50)}};_V_.flash.onEvent=function(swfID,eventName){var player=_V_.el(swfID).player;player.triggerEvent(eventName)};_V_.flash.onError=function(swfID,err){var player=_V_.el(swfID).player;player.triggerEvent("error");_V_.log("Flash Error",err,swfID)};_V_.flash.version=function(){var version="0,0,0";try{version=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(e){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){version=(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(e){}}return version.split(",")};_V_.flash.embed=function(swf,placeHolder,flashVars,params,attributes){var code=_V_.flash.getEmbedCode(swf,flashVars,params,attributes),obj=_V_.createElement("div",{innerHTML:code}).childNodes[0],par=placeHolder.parentNode;placeHolder.parentNode.replaceChild(obj,placeHolder);if(_V_.isIE()){var newObj=par.childNodes[0];setTimeout(function(){newObj.style.display="block"},1000)}return obj};_V_.flash.getEmbedCode=function(swf,flashVars,params,attributes){var objTag='<object type="application/x-shockwave-flash"',flashVarsString="",paramsString="";attrsString="";if(flashVars){_V_.eachProp(flashVars,function(key,val){flashVarsString+=(key+"="+val+"&")})}params=_V_.merge({movie:swf,flashvars:flashVarsString,allowScriptAccess:"always",allowNetworking:"all"},params);_V_.eachProp(params,function(key,val){paramsString+='<param name="'+key+'" value="'+val+'" />'});attributes=_V_.merge({data:swf,width:"100%",height:"100%"},attributes);_V_.eachProp(attributes,function(key,val){attrsString+=(key+'="'+val+'" ')});return objTag+attrsString+">"+paramsString+"</object>"};_V_.Control=_V_.Component.extend({buildCSSClass:function(){return"vjs-control "+this._super()}});_V_.ControlBar=_V_.Component.extend({options:{loadEvent:"play",components:{playToggle:{},fullscreenToggle:{},currentTimeDisplay:{},timeDivider:{},durationDisplay:{},remainingTimeDisplay:{},progressControl:{},volumeControl:{},muteToggle:{}}},init:function(player,options){this._super(player,options);player.one("play",this.proxy(function(){this.fadeIn();this.player.addEvent("mouseover",this.proxy(this.fadeIn));this.player.addEvent("mouseout",this.proxy(this.fadeOut))}))},createElement:function(){return _V_.createElement("div",{className:"vjs-controls"})},fadeIn:function(){this._super();this.player.triggerEvent("controlsvisible")},fadeOut:function(){this._super();this.player.triggerEvent("controlshidden")},lockShowing:function(){this.el.style.opacity="1"}});_V_.Button=_V_.Control.extend({init:function(player,options){this._super(player,options);this.addEvent("click",this.onClick);this.addEvent("focus",this.onFocus);this.addEvent("blur",this.onBlur)},createElement:function(type,attrs){attrs=_V_.merge({className:this.buildCSSClass(),innerHTML:'<div><span class="vjs-control-text">'+(this.buttonText||"Need Text")+"</span></div>",role:"button",tabIndex:0},attrs);return this._super(type,attrs)},onClick:function(){},onFocus:function(){_V_.addEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))},onKeyPress:function(event){if(event.which==32||event.which==13){event.preventDefault();this.onClick()}},onBlur:function(){_V_.removeEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))}});_V_.PlayButton=_V_.Button.extend({buttonText:"Play",buildCSSClass:function(){return"vjs-play-button "+this._super()},onClick:function(){this.player.play()}});_V_.PauseButton=_V_.Button.extend({buttonText:"Pause",buildCSSClass:function(){return"vjs-pause-button "+this._super()},onClick:function(){this.player.pause()}});_V_.PlayToggle=_V_.Button.extend({buttonText:"Play",init:function(player,options){this._super(player,options);player.addEvent("play",_V_.proxy(this,this.onPlay));player.addEvent("pause",_V_.proxy(this,this.onPause))},buildCSSClass:function(){return"vjs-play-control "+this._super()},onClick:function(){if(this.player.paused()){this.player.play()}else{this.player.pause()}},onPlay:function(){_V_.removeClass(this.el,"vjs-paused");_V_.addClass(this.el,"vjs-playing")},onPause:function(){_V_.removeClass(this.el,"vjs-playing");_V_.addClass(this.el,"vjs-paused")}});_V_.FullscreenToggle=_V_.Button.extend({buttonText:"Fullscreen",buildCSSClass:function(){return"vjs-fullscreen-control "+this._super()},onClick:function(){if(!this.player.isFullScreen){this.player.requestFullScreen()}else{this.player.cancelFullScreen()}}});_V_.BigPlayButton=_V_.Button.extend({init:function(player,options){this._super(player,options);player.addEvent("play",_V_.proxy(this,this.hide));player.addEvent("ended",_V_.proxy(this,this.show))},createElement:function(){return this._super("div",{className:"vjs-big-play-button",innerHTML:"<span></span>"})},onClick:function(){if(this.player.currentTime()){this.player.currentTime(0)}this.player.play()}});_V_.LoadingSpinner=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("canplay",_V_.proxy(this,this.hide));player.addEvent("canplaythrough",_V_.proxy(this,this.hide));player.addEvent("playing",_V_.proxy(this,this.hide));player.addEvent("seeking",_V_.proxy(this,this.show));player.addEvent("seeked",_V_.proxy(this,this.hide));player.addEvent("error",_V_.proxy(this,this.show));player.addEvent("waiting",_V_.proxy(this,this.show))},createElement:function(){var classNameSpinner,innerHtmlSpinner;if(typeof this.player.el.style.WebkitBorderRadius=="string"||typeof this.player.el.style.MozBorderRadius=="string"||typeof this.player.el.style.KhtmlBorderRadius=="string"||typeof this.player.el.style.borderRadius=="string"){classNameSpinner="vjs-loading-spinner";innerHtmlSpinner="<div class='ball1'></div><div class='ball2'></div><div class='ball3'></div><div class='ball4'></div><div class='ball5'></div><div class='ball6'></div><div class='ball7'></div><div class='ball8'></div>"}else{classNameSpinner="vjs-loading-spinner-fallback";innerHtmlSpinner=""}return this._super("div",{className:classNameSpinner,innerHTML:innerHtmlSpinner})}});_V_.CurrentTimeDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("timeupdate",_V_.proxy(this,this.updateContent))},createElement:function(){var el=this._super("div",{className:"vjs-current-time vjs-time-controls vjs-control"});this.content=_V_.createElement("div",{className:"vjs-current-time-display",innerHTML:"0:00"});el.appendChild(_V_.createElement("div").appendChild(this.content));return el},updateContent:function(){var time=(this.player.scrubbing)?this.player.values.currentTime:this.player.currentTime();this.content.innerHTML=_V_.formatTime(time,this.player.duration())}});_V_.DurationDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("timeupdate",_V_.proxy(this,this.updateContent))},createElement:function(){var el=this._super("div",{className:"vjs-duration vjs-time-controls vjs-control"});this.content=_V_.createElement("div",{className:"vjs-duration-display",innerHTML:"0:00"});el.appendChild(_V_.createElement("div").appendChild(this.content));return el},updateContent:function(){if(this.player.duration()){this.content.innerHTML=_V_.formatTime(this.player.duration())}}});_V_.TimeDivider=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-time-divider",innerHTML:"<div><span>/</span></div>"})}});_V_.RemainingTimeDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("timeupdate",_V_.proxy(this,this.updateContent))},createElement:function(){var el=this._super("div",{className:"vjs-remaining-time vjs-time-controls vjs-control"});this.content=_V_.createElement("div",{className:"vjs-remaining-time-display",innerHTML:"-0:00"});el.appendChild(_V_.createElement("div").appendChild(this.content));return el},updateContent:function(){if(this.player.duration()){this.content.innerHTML="-"+_V_.formatTime(this.player.remainingTime())}}});_V_.Slider=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent(this.playerEvent,_V_.proxy(this,this.update));this.addEvent("mousedown",this.onMouseDown);this.addEvent("focus",this.onFocus);this.addEvent("blur",this.onBlur);this.player.addEvent("controlsvisible",this.proxy(this.update));this.update()},createElement:function(type,attrs){attrs=_V_.merge({role:"slider","aria-valuenow":0,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0},attrs);return this._super(type,attrs)},onMouseDown:function(event){event.preventDefault();_V_.blockTextSelection();_V_.addEvent(document,"mousemove",_V_.proxy(this,this.onMouseMove));_V_.addEvent(document,"mouseup",_V_.proxy(this,this.onMouseUp));this.onMouseMove(event)},onMouseUp:function(event){_V_.unblockTextSelection();_V_.removeEvent(document,"mousemove",this.onMouseMove,false);_V_.removeEvent(document,"mouseup",this.onMouseUp,false);this.update()},update:function(){var barProgress,progress=this.getPercent();handle=this.handle,bar=this.bar;if(isNaN(progress)){progress=0}barProgress=progress;if(handle){var box=this.el,boxWidth=box.offsetWidth,handleWidth=handle.el.offsetWidth,handlePercent=(handleWidth)?handleWidth/boxWidth:0,boxAdjustedPercent=1-handlePercent;adjustedProgress=progress*boxAdjustedPercent,barProgress=adjustedProgress+(handlePercent/2);handle.el.style.left=_V_.round(adjustedProgress*100,2)+"%"}bar.el.style.width=_V_.round(barProgress*100,2)+"%"},calculateDistance:function(event){var box=this.el,boxX=_V_.findPosX(box),boxW=box.offsetWidth,handle=this.handle;if(handle){var handleW=handle.el.offsetWidth;boxX=boxX+(handleW/2);boxW=boxW-handleW}return Math.max(0,Math.min(1,(event.pageX-boxX)/boxW))},onFocus:function(event){_V_.addEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))},onKeyPress:function(event){if(event.which==37){event.preventDefault();this.stepBack()}else{if(event.which==39){event.preventDefault();this.stepForward()}}},onBlur:function(event){_V_.removeEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))}});_V_.ProgressControl=_V_.Component.extend({options:{components:{seekBar:{}}},createElement:function(){return this._super("div",{className:"vjs-progress-control vjs-control"})}});_V_.SeekBar=_V_.Slider.extend({options:{components:{loadProgressBar:{},bar:{componentClass:"PlayProgressBar"},handle:{componentClass:"SeekHandle"}}},playerEvent:"timeupdate",init:function(player,options){this._super(player,options)},createElement:function(){return this._super("div",{className:"vjs-progress-holder"})},getPercent:function(){return this.player.currentTime()/this.player.duration()},onMouseDown:function(event){this._super(event);this.player.scrubbing=true;this.videoWasPlaying=!this.player.paused();this.player.pause()},onMouseMove:function(event){var newTime=this.calculateDistance(event)*this.player.duration();if(newTime==this.player.duration()){newTime=newTime-0.1}this.player.currentTime(newTime)},onMouseUp:function(event){this._super(event);this.player.scrubbing=false;if(this.videoWasPlaying){this.player.play()}},stepForward:function(){this.player.currentTime(this.player.currentTime()+1)},stepBack:function(){this.player.currentTime(this.player.currentTime()-1)}});_V_.LoadProgressBar=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("progress",_V_.proxy(this,this.update))},createElement:function(){return this._super("div",{className:"vjs-load-progress",innerHTML:'<span class="vjs-control-text">Loaded: 0%</span>'})},update:function(){if(this.el.style){this.el.style.width=_V_.round(this.player.bufferedPercent()*100,2)+"%"}}});_V_.PlayProgressBar=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-play-progress",innerHTML:'<span class="vjs-control-text">Progress: 0%</span>'})}});_V_.SeekHandle=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-seek-handle",innerHTML:'<span class="vjs-control-text">00:00</span>'})}});_V_.VolumeControl=_V_.Component.extend({options:{components:{volumeBar:{}}},createElement:function(){return this._super("div",{className:"vjs-volume-control vjs-control"})}});_V_.VolumeBar=_V_.Slider.extend({options:{components:{bar:{componentClass:"VolumeLevel"},handle:{componentClass:"VolumeHandle"}}},playerEvent:"volumechange",createElement:function(){return this._super("div",{className:"vjs-volume-bar"})},onMouseMove:function(event){this.player.volume(this.calculateDistance(event))},getPercent:function(){return this.player.volume()},stepForward:function(){this.player.volume(this.player.volume()+0.1)},stepBack:function(){this.player.volume(this.player.volume()-0.1)}});_V_.VolumeLevel=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-volume-level",innerHTML:'<span class="vjs-control-text"></span>'})}});_V_.VolumeHandle=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-volume-handle",innerHTML:'<span class="vjs-control-text"></span>'})}});_V_.MuteToggle=_V_.Button.extend({init:function(player,options){this._super(player,options);player.addEvent("volumechange",_V_.proxy(this,this.update))},createElement:function(){return this._super("div",{className:"vjs-mute-control vjs-control",innerHTML:'<div><span class="vjs-control-text">Mute</span></div>'})},onClick:function(event){this.player.muted(this.player.muted()?false:true)},update:function(event){var vol=this.player.volume(),level=3;if(vol==0||this.player.muted()){level=0}else{if(vol<0.33){level=1}else{if(vol<0.67){level=2}}}_V_.each.call(this,[0,1,2,3],function(i){_V_.removeClass(this.el,"vjs-vol-"+i)});_V_.addClass(this.el,"vjs-vol-"+level)}});_V_.PosterImage=_V_.Button.extend({init:function(player,options){this._super(player,options);if(!this.player.options.poster){this.hide()}player.addEvent("play",_V_.proxy(this,this.hide))},createElement:function(){return _V_.createElement("img",{className:"vjs-poster",src:this.player.options.poster,tabIndex:-1})},onClick:function(){this.player.play()}});_V_.Menu=_V_.Component.extend({init:function(player,options){this._super(player,options)},addItem:function(component){this.addComponent(component);component.addEvent("click",this.proxy(function(){this.unlockShowing()}))},createElement:function(){return this._super("ul",{className:"vjs-menu"})}});_V_.MenuItem=_V_.Button.extend({init:function(player,options){this._super(player,options);if(options.selected){this.addClass("vjs-selected")}},createElement:function(type,attrs){return this._super("li",_V_.merge({className:"vjs-menu-item",innerHTML:this.options.label},attrs))},onClick:function(){this.selected(true)},selected:function(selected){if(selected){this.addClass("vjs-selected")}else{this.removeClass("vjs-selected")}}});_V_.merge(_V_.Player.prototype,{addTextTracks:function(trackObjects){var tracks=this.textTracks=(this.textTracks)?this.textTracks:[],i=0,j=trackObjects.length,track,Kind;for(;i<j;i++){Kind=_V_.uc(trackObjects[i].kind||"subtitles");track=new _V_[Kind+"Track"](this,trackObjects[i]);tracks.push(track);if(track["default"]){this.ready(_V_.proxy(track,track.show))}}return this},showTextTrack:function(id,disableSameKind){var tracks=this.textTracks,i=0,j=tracks.length,track,showTrack,kind;for(;i<j;i++){track=tracks[i];if(track.id===id){track.show();showTrack=track}else{if(disableSameKind&&track.kind==disableSameKind&&track.mode>0){track.disable()}}}kind=(showTrack)?showTrack.kind:((disableSameKind)?disableSameKind:false);if(kind){this.triggerEvent(kind+"trackchange")}return this}});_V_.Track=_V_.Component.extend({init:function(player,options){this._super(player,options);_V_.merge(this,{id:options.id||("vjs_"+options.kind+"_"+options.language+"_"+_V_.guid++),src:options.src,"default":options["default"],title:options.title,language:options.srclang,label:options.label,cues:[],activeCues:[],readyState:0,mode:0})},createElement:function(){return this._super("div",{className:"vjs-"+this.kind+" vjs-text-track"})},show:function(){this.activate();this.mode=2;this._super()},hide:function(){this.activate();this.mode=1;this._super()},disable:function(){if(this.mode==2){this.hide()}this.deactivate();this.mode=0},activate:function(){if(this.readyState==0){this.load()}if(this.mode==0){this.player.addEvent("timeupdate",this.proxy(this.update,this.id));this.player.addEvent("ended",this.proxy(this.reset,this.id));if(this.kind=="captions"||this.kind=="subtitles"){this.player.textTrackDisplay.addComponent(this)}}},deactivate:function(){this.player.removeEvent("timeupdate",this.proxy(this.update,this.id));this.player.removeEvent("ended",this.proxy(this.reset,this.id));this.reset();this.player.textTrackDisplay.removeComponent(this)},load:function(){if(this.readyState==0){this.readyState=1;_V_.get(this.src,this.proxy(this.parseCues),this.proxy(this.onError))}},onError:function(err){this.error=err;this.readyState=3;this.triggerEvent("error")},parseCues:function(srcContent){var cue,time,text,lines=srcContent.split("\n"),line="",id;for(var i=1,j=lines.length;i<j;i++){line=_V_.trim(lines[i]);if(line){if(line.indexOf("-->")==-1){id=line;line=_V_.trim(lines[++i])}else{id=this.cues.length}cue={id:id,index:this.cues.length};time=line.split(" --> ");cue.startTime=this.parseCueTime(time[0]);cue.endTime=this.parseCueTime(time[1]);text=[];while(lines[++i]&&(line=_V_.trim(lines[i]))){text.push(line)}cue.text=text.join("<br/>");this.cues.push(cue)}}this.readyState=2;this.triggerEvent("loaded")},parseCueTime:function(timeText){var parts=timeText.split(":"),time=0,hours,minutes,other,seconds,ms,flags;if(parts.length==3){hours=parts[0];minutes=parts[1];other=parts[2]}else{hours=0;minutes=parts[0];other=parts[1]}other=other.split(/\s+/);seconds=other.splice(0,1)[0];seconds=seconds.split(/\.|,/);ms=parseFloat(seconds[1]);seconds=seconds[0];time+=parseFloat(hours)*3600;time+=parseFloat(minutes)*60;time+=parseFloat(seconds);if(ms){time+=ms/1000}return time},update:function(){if(this.cues.length>0){var time=this.player.currentTime();if(this.prevChange===undefined||time<this.prevChange||this.nextChange<=time){var cues=this.cues,newNextChange=this.player.duration(),newPrevChange=0,reverse=false,newCues=[],firstActiveIndex,lastActiveIndex,html="",cue,i,j;if(time>=this.nextChange||this.nextChange===undefined){i=(this.firstActiveIndex!==undefined)?this.firstActiveIndex:0}else{reverse=true;i=(this.lastActiveIndex!==undefined)?this.lastActiveIndex:cues.length-1}while(true){cue=cues[i];if(cue.endTime<=time){newPrevChange=Math.max(newPrevChange,cue.endTime);if(cue.active){cue.active=false}}else{if(time<cue.startTime){newNextChange=Math.min(newNextChange,cue.startTime);if(cue.active){cue.active=false}if(!reverse){break}}else{if(reverse){newCues.splice(0,0,cue);if(lastActiveIndex===undefined){lastActiveIndex=i}firstActiveIndex=i}else{newCues.push(cue);if(firstActiveIndex===undefined){firstActiveIndex=i}lastActiveIndex=i}newNextChange=Math.min(newNextChange,cue.endTime);newPrevChange=Math.max(newPrevChange,cue.startTime);cue.active=true}}if(reverse){if(i===0){break}else{i--}}else{if(i===cues.length-1){break}else{i++}}}this.activeCues=newCues;this.nextChange=newNextChange;this.prevChange=newPrevChange;this.firstActiveIndex=firstActiveIndex;this.lastActiveIndex=lastActiveIndex;this.updateDisplay();this.triggerEvent("cuechange")}}},updateDisplay:function(){var cues=this.activeCues,html="",i=0,j=cues.length;for(;i<j;i++){html+="<span class='vjs-tt-cue'>"+cues[i].text+"</span>"}this.el.innerHTML=html},reset:function(){this.nextChange=0;this.prevChange=this.player.duration();this.firstActiveIndex=0;this.lastActiveIndex=0}});_V_.CaptionsTrack=_V_.Track.extend({kind:"captions"});_V_.SubtitlesTrack=_V_.Track.extend({kind:"subtitles"});_V_.ChaptersTrack=_V_.Track.extend({kind:"chapters"});_V_.TextTrackDisplay=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-text-track-display"})}});_V_.TextTrackMenuItem=_V_.MenuItem.extend({init:function(player,options){var track=this.track=options.track;options.label=track.label;options.selected=track["default"];this._super(player,options);this.player.addEvent(track.kind+"trackchange",_V_.proxy(this,this.update))},onClick:function(){this._super();this.player.showTextTrack(this.track.id,this.track.kind)},update:function(){if(this.track.mode==2){this.selected(true)}else{this.selected(false)}}});_V_.OffTextTrackMenuItem=_V_.TextTrackMenuItem.extend({init:function(player,options){options.track={kind:options.kind,player:player,label:"Off"};this._super(player,options)},onClick:function(){this._super();this.player.showTextTrack(this.track.id,this.track.kind)},update:function(){var tracks=this.player.textTracks,i=0,j=tracks.length,track,off=true;for(;i<j;i++){track=tracks[i];if(track.kind==this.track.kind&&track.mode==2){off=false}}if(off){this.selected(true)}else{this.selected(false)}}});_V_.TextTrackButton=_V_.Button.extend({init:function(player,options){this._super(player,options);this.menu=this.createMenu();if(this.items.length===0){this.hide()}},createMenu:function(){var menu=new _V_.Menu(this.player);menu.el.appendChild(_V_.createElement("li",{className:"vjs-menu-title",innerHTML:_V_.uc(this.kind)}));menu.addItem(new _V_.OffTextTrackMenuItem(this.player,{kind:this.kind}));this.items=this.createItems();this.each(this.items,function(item){menu.addItem(item)});this.addComponent(menu);return menu},createItems:function(){var items=[];this.each(this.player.textTracks,function(track){if(track.kind===this.kind){items.push(new _V_.TextTrackMenuItem(this.player,{track:track}))}});return items},buildCSSClass:function(){return this.className+" vjs-menu-button "+this._super()},onFocus:function(){this.menu.lockShowing();_V_.one(this.menu.el.childNodes[this.menu.el.childNodes.length-1],"blur",this.proxy(function(){this.menu.unlockShowing()}))},onBlur:function(){},onClick:function(){this.one("mouseout",this.proxy(function(){this.menu.unlockShowing();this.el.blur()}))}});_V_.CaptionsButton=_V_.TextTrackButton.extend({kind:"captions",buttonText:"Captions",className:"vjs-captions-button"});_V_.SubtitlesButton=_V_.TextTrackButton.extend({kind:"subtitles",buttonText:"Subtitles",className:"vjs-subtitles-button"});_V_.ChaptersButton=_V_.TextTrackButton.extend({kind:"chapters",buttonText:"Chapters",className:"vjs-chapters-button",createItems:function(chaptersTrack){var items=[];this.each(this.player.textTracks,function(track){if(track.kind===this.kind){items.push(new _V_.TextTrackMenuItem(this.player,{track:track}))}});return items},createMenu:function(){var tracks=this.player.textTracks,i=0,j=tracks.length,track,chaptersTrack,items=this.items=[];for(;i<j;i++){track=tracks[i];if(track.kind==this.kind&&track["default"]){if(track.readyState<2){this.chaptersTrack=track;track.addEvent("loaded",this.proxy(this.createMenu));return}else{chaptersTrack=track;break}}}var menu=this.menu=new _V_.Menu(this.player);menu.el.appendChild(_V_.createElement("li",{className:"vjs-menu-title",innerHTML:_V_.uc(this.kind)}));if(chaptersTrack){var cues=chaptersTrack.cues,i=0,j=cues.length,cue,mi;for(;i<j;i++){cue=cues[i];mi=new _V_.ChaptersTrackMenuItem(this.player,{track:chaptersTrack,cue:cue});items.push(mi);menu.addComponent(mi)}}this.addComponent(menu);if(this.items.length>0){this.show()}return menu}});_V_.ChaptersTrackMenuItem=_V_.MenuItem.extend({init:function(player,options){var track=this.track=options.track,cue=this.cue=options.cue,currentTime=player.currentTime();options.label=cue.text;options.selected=(cue.startTime<=currentTime&¤tTime<cue.endTime);this._super(player,options);track.addEvent("cuechange",_V_.proxy(this,this.update))},onClick:function(){this._super();this.player.currentTime(this.cue.startTime);this.update(this.cue.startTime)},update:function(time){var cue=this.cue,currentTime=this.player.currentTime();if(cue.startTime<=currentTime&¤tTime<cue.endTime){this.selected(true)}else{this.selected(false)}}});_V_.merge(_V_.ControlBar.prototype.options.components,{subtitlesButton:{},captionsButton:{},chaptersButton:{}});_V_.autoSetup=function(){var options,vid,player,vids=document.getElementsByTagName("video");if(vids&&vids.length>0){for(var i=0,j=vids.length;i<j;i++){vid=vids[i];if(vid&&vid.getAttribute){if(vid.player===undefined){options=vid.getAttribute("data-setup");if(options!==null){options=JSON.parse(options||"{}");player=_V_(vid,options)}}}else{_V_.autoSetupTimeout(1);break}}}else{if(!_V_.windowLoaded){_V_.autoSetupTimeout(1)}}};_V_.autoSetupTimeout=function(wait){setTimeout(_V_.autoSetup,wait)};_V_.addEvent(window,"load",function(){_V_.windowLoaded=true});_V_.autoSetup();window.VideoJS=window._V_=VideoJS})(window);
\ No newline at end of file diff --git a/install-sh b/install-sh new file mode 100755 index 00000000..377bb868 --- /dev/null +++ b/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# 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 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/m4/python.m4 b/m4/python.m4 new file mode 100644 index 00000000..f8b197fe --- /dev/null +++ b/m4/python.m4 @@ -0,0 +1,638 @@ +# Copyright 2012, 2013 Brandon Invergo <brandon@invergo.net> +# +# This file is part of pyconfigure. This program is free +# software; you can redistribute it and/or modify it under the +# terms of the GNU 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 General Public License for more details. +# +# Under Section 7 of GPL version 3, you are granted additional +# permissions described in the Autoconf Configure Script Exception, +# version 3.0, as published by the Free Software Foundation. +# +# You should have received a copy of the GNU General Public License +# and a copy of the Autoconf Configure Script Exception along with +# this program; see the files COPYINGv3 and COPYING.EXCEPTION +# respectively. If not, see <http://www.gnu.org/licenses/>. + + +# Many of these macros were adapted from ones written by Andrew Dalke +# and James Henstridge and are included with the Automake utility +# under the following copyright terms: +# +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Table of Contents: +# +# 1. Language selection +# and routines to produce programs in a given language. +# +# 2. Producing programs in a given language. +# +# 3. Looking for a compiler +# And possibly the associated preprocessor. +# +# 4. Looking for specific libs & functionality + + +## ----------------------- ## +## 1. Language selection. ## +## ----------------------- ## + + +# AC_LANG(Python) +# --------------- +AC_LANG_DEFINE([Python], [py], [PY], [PYTHON], [], +[ac_ext=py +ac_compile='chmod +x conftest.$ac_ext >&AS_MESSAGE_LOG_FD' +ac_link='chmod +x conftest.$ac_ext && cp conftest.$ac_ext conftest >&AS_MESSAGE_LOG_FD' +]) + + +# AC_LANG_PYTHON +# -------------- +AU_DEFUN([AC_LANG_PYTHON], [AC_LANG(Python)]) + + +## ----------------------- ## +## 2. Producing programs. ## +## ----------------------- ## + + +# AC_LANG_PROGRAM(Python)([PROLOGUE], [BODY]) +# ------------------------------------------- +m4_define([AC_LANG_PROGRAM(Python)], [dnl +@%:@!$PYTHON +$1 +m4_if([$2], [], [], [dnl +if __name__ == '__main__': +$2])]) + + +# _AC_LANG_IO_PROGRAM(Python) +# --------------------------- +# Produce source that performs I/O. +m4_define([_AC_LANG_IO_PROGRAM(Python)], +[AC_LANG_PROGRAM([dnl +import sys +try: + h = open('conftest.out') +except: + sys.exit(1) +else: + close(h) + sys.exit(0) +], [])]) + + +# _AC_LANG_CALL(Python)([PROLOGUE], [FUNCTION]) +# --------------------- +# Produce source that calls FUNCTION +m4_define([_AC_LANG_CALL(Python)], +[AC_LANG_PROGRAM([$1], [$2])]) + + +## -------------------------------------------- ## +## 3. Looking for Compilers and Interpreters. ## +## -------------------------------------------- ## + + +AC_DEFUN([AC_LANG_COMPILER(Python)], +[AC_REQUIRE([AC_PROG_PYTHON])]) + + +# PC_INIT([MIN_VER], [MAX_VER]) +# ----------------------------- +# Initialize pyconfigure, finding a Python interpreter with a given +# minimum and/or maximum version. +AC_DEFUN([PC_INIT], +[AC_ARG_VAR([PYTHON], [the Python interpreter]) +dnl The default minimum version is 2.0 +m4_define_default([pc_min_ver], m4_ifval([$1], [$1], [2.0])) +dnl The default maximum version is 3.3 +m4_define_default([pc_max_ver], m4_ifval([$2], [$2], [3.3])) +dnl Build up a list of possible interpreter names. +m4_define_default([_PC_PYTHON_INTERPRETER_LIST], +dnl Construct a comma-separated list of interpreter names (python2.6, +dnl python2.7, etc). We only care about the first 3 characters of the +dnl version strings (major-dot-minor; not +dnl major-dot-minor-dot-bugfix[-dot-whatever]) + [m4_foreach([pc_ver], + m4_esyscmd_s(seq -s[[", "]] -f["[[%.1f]]"] m4_substr(pc_max_ver, [0], [3]) -0.1 m4_substr(pc_min_ver, [0], [3])), +dnl Remove python2.8 and python2.9 since they will never exist + [m4_bmatch(pc_ver, [2.[89]], [], [python]pc_ver)] ) \ +dnl If we want some Python 3 versions (max version >= 3.0), +dnl also search for "python3" +m4_if(m4_version_compare(pc_max_ver, [2.9]), [1], [python3], []) \ +dnl If we want some Python 2 versions (min version <= 2.7), +dnl also search for "python2". Finally, also search for plain ol' "python" +m4_if(m4_version_compare(pc_min_ver, [2.8]), [-1], [python2], []) [python]]) +dnl Do the actual search at last. +AC_PATH_PROGS(PYTHON, [_PC_PYTHON_INTERPRETER_LIST]) +dnl If we found something, do a sanity check that the interpreter really +dnl has the version its name would suggest. +m4_ifval([PYTHON], + [PC_PYTHON_VERIFY_VERSION([>=], [pc_min_ver], + [AC_MSG_RESULT([yes])], + [AC_MSG_FAILURE([No compatible Python interpreter found. If you're sure that you have one, try setting the PYTHON environment variable to the location of the interpreter.])])]) +m4_ifval([PYTHON], + [PC_PYTHON_VERIFY_VERSION([<=], [pc_max_ver], + [AC_MSG_RESULT([yes])], + [AC_MSG_FAILURE([No compatible Python interpreter found. If you're sure that you have one, try setting the PYTHON environment variable to the location of the interpreter.])])]) +])# PC_INIT + +# AC_PROG_PYTHON(PROG-TO-CHECK-FOR) +# --------------------------------- +# Find a Python interpreter. Python versions prior to 2.0 are not +# supported. (2.0 was released on October 16, 2000). +AC_DEFUN([AC_PROG_PYTHON], +[AC_ARG_VAR([PYTHON], [the Python interpreter]) +m4_define_default([_PC_PYTHON_INTERPRETER_LIST], + [python python3 python3.3 python3.2 python3.1 python3.0 python2 python2.7 dnl + python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) +m4_ifval([$1], + [AC_PATH_PROGS(PYTHON, [$1 _PC_PYTHON_INTERPRETER_LIST])], + [AC_PATH_PROGS(PYTHON, [_PC_PYTHON_INTERPRETER_LIST])]) +]) + + +# PC_PYTHON_PROG_PYTHON_CONFIG(PROG-TO-CHECK-FOR) +# ---------------------------------------------- +# Find the python-config program +AC_DEFUN([PC_PYTHON_PROG_PYTHON_CONFIG], +[AC_REQUIRE([PC_INIT])[]dnl +AC_ARG_VAR([PYTHON_CONFIG], [the Python-config program]) +dnl python-config's binary name is normally based on the Python interpreter's +dnl binary name (i.e. python2.7 -> python2.7-config) +m4_define([_PYTHON_BASENAME], [`basename $PYTHON`]) +m4_ifval([$1], + [AC_PATH_PROGS(PYTHON_CONFIG, [$1 _PYTHON_BASENAME-config])], + [AC_PATH_PROG(PYTHON_CONFIG, _PYTHON_BASENAME-config)]) +]) # PC_PYTHON_PROG_PYTHON_CONFIG + + +# PC_PYTHON_VERIFY_VERSION(RELATION, VERSION, [ACTION-IF-TRUE], [ACTION-IF-NOT-FOUND]) +# --------------------------------------------------------------------------- +# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. +# Run ACTION-IF-FALSE otherwise. +# Specify RELATION as any mathematical comparison "<", ">", "<=", ">=", "==" or "!=" +# This test uses sys.hexversion instead of the string equivalent (first +# word of sys.version), in order to cope with versions such as 2.2c1. +# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). +AC_DEFUN([PC_PYTHON_VERIFY_VERSION], +[m4_define([pc_python_safe_ver], m4_bpatsubsts($2, [\.], [_])) +AC_CACHE_CHECK([if Python $1 '$2'], + [[pc_cv_python_min_version_]pc_python_safe_ver], + [AC_LANG_PUSH(Python)[]dnl + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([dnl +import sys +], [dnl + # split strings by '.' and convert to numeric. Append some zeros + # because we need at least 4 digits for the hex conversion. + # map returns an iterator in Python 3.0 and a list in 2.x + reqver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] + reqverhex = 0 + # xrange is not present in Python 3.0 and range returns an iterator + for i in list(range(4)): + reqverhex = (reqverhex << 8) + reqver[[i]] + if sys.hexversion $1 reqverhex: + sys.exit() + else: + sys.exit(1) +])], + [[pc_cv_python_req_version_]pc_python_safe_ver="yes"], + [[pc_cv_python_req_version_]pc_python_safe_ver="no"]) + AC_LANG_POP(Python)[]dnl + ]) +AS_IF([test "$[pc_cv_python_req_version_]pc_python_safe_ver" = "no"], [$4], [$3]) +])# PC_PYTHON_VERIFY_VERSION + + +# PC_PYTHON_CHECK_VERSION +# ----------------------- +# Query Python for its version number. Getting [:3] seems to be +# the best way to do this; it's what "site.py" does in the standard +# library. +AC_DEFUN([PC_PYTHON_CHECK_VERSION], +[AC_REQUIRE([PC_INIT])[]dnl +AC_CACHE_CHECK([for $1 version], + [pc_cv_python_version], + [AC_LANG_PUSH(Python)[]dnl + AC_LANG_CONFTEST([ + AC_LANG_PROGRAM([dnl +import sys +], [dnl + sys.stdout.write(sys.version[[:3]]) +])]) + pc_cv_python_version=`$PYTHON conftest.py` + AC_LANG_POP(Python)[]dnl + ]) +AC_SUBST([PYTHON_VERSION], [$pc_cv_python_version]) +])# PC_PYTHON_CHECK_VERSION + + +# PC_PYTHON_CHECK_PREFIX +# ---------------------- +# Use the value of $prefix for the corresponding value of +# PYTHON_PREFIX. This is made a distinct variable so it can be +# overridden if need be. However, general consensus is that you +# shouldn't need this ability. +AC_DEFUN([PC_PYTHON_CHECK_PREFIX], +[AC_REQUIRE([PC_PYTHON_PROG_PYTHON_CONFIG])[]dnl +dnl Try to get it with python-config otherwise do it from within Python +AC_CACHE_CHECK([for Python prefix], [pc_cv_python_prefix], +[if test -x "$PYTHON_CONFIG"; then + pc_cv_python_prefix=`$PYTHON_CONFIG --prefix 2>&AS_MESSAGE_LOG_FD` +else + AC_LANG_PUSH(Python)[]dnl + pc_cv_python_prefix=AC_LANG_CONFTEST([AC_LANG_PROGRAM([dnl +import sys +], [dnl + sys.exit(sys.prefix) +])]) + AC_LANG_POP(Python)[]dnl +fi]) +AC_SUBST([PYTHON_PREFIX], [$pc_cv_python_prefix])]) + + +# PC_PYTHON_CHECK_EXEC_PREFIX +# -------------------------- +# Like above, but for $exec_prefix +AC_DEFUN([PC_PYTHON_CHECK_EXEC_PREFIX], +[AC_REQUIRE([PC_PYTHON_PROG_PYTHON_CONFIG])[]dnl +dnl Try to get it with python-config otherwise do it from within Python +AC_CACHE_CHECK([for Python exec-prefix], [pc_cv_python_exec_prefix], +[if test -x "$PYTHON_CONFIG"; then + pc_cv_python_exec_prefix=`$PYTHON_CONFIG --exec-prefix 2>&AS_MESSAGE_LOG_FD` +else + AC_LANG_PUSH(Python)[]dnl + pc_cv_python_exec_prefix=AC_LANG_CONFTEST([AC_LANG_PROGRAM([dnl +import sys +], [dnl + sys.exit(sys.exec_prefix) +])]) + AC_LANG_POP(Python)[]dnl +fi +]) +AC_SUBST([PYTHON_EXEC_PREFIX], [$pc_cv_python_exec_prefix])]) + + +# PC_PYTHON_CHECK_INCLUDES +# ------------------------ +# Find the Python header file include flags (ie +# '-I/usr/include/python') +AC_DEFUN([PC_PYTHON_CHECK_INCLUDES], +[AC_REQUIRE([PC_PYTHON_PROG_PYTHON_CONFIG])[]dnl +dnl Try to find the headers location with python-config otherwise guess +AC_CACHE_CHECK([for Python includes], [pc_cv_python_includes], +[if test -x "$PYTHON_CONFIG"; then + pc_cv_python_includes=`$PYTHON_CONFIG --includes 2>&AS_MESSAGE_LOG_FD` +else + pc_cv_python_includes="[-I$includedir/$_PYTHON_BASENAME]m4_ifdef(PYTHON_ABI_FLAGS, + PYTHON_ABI_FLAGS,)" +fi +]) +AC_SUBST([PYTHON_INCLUDES], [$pc_cv_python_includes])]) + + +# PC_PYTHON_CHECK_HEADERS([ACTION-IF-PRESENT], [ACTION-IF-ABSENT]) +# ----------------------- +# Check for the presence and usability of Python.h +AC_DEFUN([PC_PYTHON_CHECK_HEADERS], +[AC_REQUIRE([PC_PYTHON_CHECK_INCLUDES])[]dnl +pc_cflags_store=$CPPFLAGS +CPPFLAGS="$CFLAGS $PYTHON_INCLUDES" +AC_CHECK_HEADER([Python.h], [$1], [$2]) +CPPFLAGS=$pc_cflags_store +]) + + +# PC_PYTHON_CHECK_LIBS +# -------------------- +# Find the Python lib flags (ie '-lpython') +AC_DEFUN([PC_PYTHON_CHECK_LIBS], +[AC_REQUIRE([PC_PYTHON_PROG_PYTHON_CONFIG])[]dnl +dnl Try to find the lib flags with python-config otherwise guess +AC_CACHE_CHECK([for Python libs], [pc_cv_python_libs], +[if test -x "$PYTHON_CONFIG"; then + pc_cv_python_libs=`$PYTHON_CONFIG --libs 2>&AS_MESSAGE_LOG_FD` +else + pc_cv_python_libs="[-l$_PYTHON_BASENAME]m4_ifdef(PYTHON_ABI_FLAGS, PYTHON_ABI_FLAGS,)" +fi +]) +AC_SUBST([PYTHON_LIBS], [$pc_cv_python_libs])]) + + +# PC_PYTHON_TEST_LIBS(LIBRARY-FUNCTION, [ACTION-IF-PRESENT], [ACTION-IF-ABSENT]) +# ------------------- +# Verify that the Python libs can be loaded +AC_DEFUN([PC_PYTHON_TEST_LIBS], +[AC_REQUIRE([PC_PYTHON_CHECK_LIBS])[]dnl +pc_libflags_store=$LIBS +for lflag in $PYTHON_LIBS; do + case $lflag in + -lpython*@:}@ + LIBS="$LIBS $lflag" + pc_libpython=`echo $lflag | sed -e 's/^-l//'` + ;; + *@:}@;; + esac +done +AC_CHECK_LIB([$pc_libpython], [$1], [$2], [$3])]) + + +# PC_PYTHON_CHECK_CFLAGS +# ---------------------- +# Find the Python CFLAGS +AC_DEFUN([PC_PYTHON_CHECK_CFLAGS], +[AC_REQUIRE([PC_PYTHON_PROG_PYTHON_CONFIG])[]dnl +dnl Try to find the CFLAGS with python-config otherwise give up +AC_CACHE_CHECK([for Python CFLAGS], [pc_cv_python_cflags], +[if test -x "$PYTHON_CONFIG"; then + pc_cv_python_cflags=`$PYTHON_CONFIG --cflags 2>&AS_MESSAGE_LOG_FD` +else + pc_cv_python_cflags= +fi +]) +AC_SUBST([PYTHON_CFLAGS], [$pc_cv_python_cflags])]) + + +# PC_PYTHON_CHECK_LDFLAGS +# ----------------------- +# Find the Python LDFLAGS +AC_DEFUN([PC_PYTHON_CHECK_LDFLAGS], +[AC_REQUIRE([PC_PYTHON_PROG_PYTHON_CONFIG])[]dnl +dnl Try to find the LDFLAGS with python-config otherwise give up +AC_CACHE_CHECK([for Python LDFLAGS], [pc_cv_python_ldflags], +[if test -x "$PYTHON_CONFIG"; then + pc_cv_python_ldflags=`$PYTHON_CONFIG --ldflags 2>&AS_MESSAGE_LOG_FD` +else + pc_cv_python_ldflags= +fi +]) +AC_SUBST([PYTHON_LDFLAGS], [$pc_cv_python_ldflags])]) + + +# PC_PYTHON_CHECK_EXTENSION_SUFFIX +# -------------------------------- +# Find the Python extension suffix (i.e. '.cpython-32.so') +AC_DEFUN([PC_PYTHON_CHECK_EXTENSION_SUFFIX], +[AC_REQUIRE([PC_PYTHON_PROG_PYTHON_CONFIG])[]dnl +dnl Try to find the suffix with python-config otherwise give up +AC_CACHE_CHECK([for Python extension suffix], [pc_cv_python_extension_suffix], +[if test -x "$PYTHON_CONFIG"; then + pc_cv_python_extension_suffix=`$PYTHON_CONFIG --extension-suffix 2>&AS_MESSAGE_LOG_FD` +else + pc_cv_python_extension_suffix= +fi +]) +AC_SUBST([PYTHON_EXTENSION_SUFFIX], [$pc_cv_python_extension_suffix])]) + + +# PC_PYTHON_CHECK_ABI_FLAGS +# ------------------------- +# Find the Python ABI flags +AC_DEFUN([PC_PYTHON_CHECK_ABI_FLAGS], +[AC_REQUIRE([PC_PYTHON_PROG_PYTHON_CONFIG])[]dnl +dnl Try to find the ABI flags with python-config otherwise give up +AC_CACHE_CHECK([for Python ABI flags], [pc_cv_python_abi_flags], +[if test -x "$PYTHON_CONFIG"; then + pc_cv_python_abi_flags=`$PYTHON_CONFIG --abiflags 2>&AS_MESSAGE_LOG_FD` +else + pc_cv_python_abi_flags= +fi +]) +AC_SUBST([PYTHON_ABI_FLAGS], [$pc_cv_python_abi_flags])]) + + +# PC_PYTHON_CHECK_PLATFORM +# ------------------------ +# At times (like when building shared libraries) you may want +# to know which OS platform Python thinks this is. +AC_DEFUN([PC_PYTHON_CHECK_PLATFORM], +[AC_REQUIRE([PC_INIT])[]dnl +dnl Get the platform from within Python (sys.platform) +AC_CACHE_CHECK([for Python platform], + [pc_cv_python_platform], + [AC_LANG_PUSH(Python)[]dnl + AC_LANG_CONFTEST([ + AC_LANG_PROGRAM([dnl +import sys +], [dnl + sys.stdout.write(sys.platform) +])]) + pc_cv_python_platform=`$PYTHON conftest.py` + AC_LANG_POP(Python)[]dnl + ]) +AC_SUBST([PYTHON_PLATFORM], [$pc_cv_python_platform]) +]) + + +# PC_PYTHON_CHECK_SITE_DIR +# --------------------- +# The directory to which new libraries are installed (i.e. the +# "site-packages" directory. +AC_DEFUN([PC_PYTHON_CHECK_SITE_DIR], +[AC_REQUIRE([PC_INIT])AC_REQUIRE([PC_PYTHON_CHECK_PREFIX])[]dnl +AC_CACHE_CHECK([for Python site-packages directory], + [pc_cv_python_site_dir], + [AC_LANG_PUSH(Python)[]dnl + if test "x$prefix" = xNONE + then + pc_py_prefix=$ac_default_prefix + else + pc_py_prefix=$prefix + fi + AC_LANG_CONFTEST([ + AC_LANG_PROGRAM([dnl +import sys +from platform import python_implementation +# sysconfig in CPython 2.7 doesn't work in virtualenv +# <https://github.com/pypa/virtualenv/issues/118> +try: + import sysconfig +except: + can_use_sysconfig = False +else: + can_use_sysconfig = True +if can_use_sysconfig: + if python_implementation() == "CPython" and sys.version[[:3]] == '2.7': + can_use_sysconfig = False +if not can_use_sysconfig: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(False, False, prefix='$pc_py_prefix') +else: + sitedir = sysconfig.get_path('purelib', vars={'base':'$pc_py_prefix'}) +], [dnl + sys.stdout.write(sitedir) +])]) + pc_cv_python_site_dir=`$PYTHON conftest.py` + AC_LANG_POP(Python)[]dnl + case $pc_cv_python_site_dir in + $pc_py_prefix*) + pc__strip_prefix=`echo "$pc_py_prefix" | sed 's|.|.|g'` + pc_cv_python_site_dir=`echo "$pc_cv_python_site_dir" | sed "s,^$pc__strip_prefix/,,"` + ;; + *) + case $pc_py_prefix in + /usr|/System*) ;; + *) + pc_cv_python_site_dir=lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + ]) +AC_SUBST([pythondir], [\${prefix}/$pc_cv_python_site_dir])])# PC_PYTHON_CHECK_SITE_DIR + +# PC_PYTHON_SITE_PACKAGE_DIR +# -------------------------- +# $PACKAGE directory under PYTHON_SITE_DIR +AC_DEFUN([PC_PYTHON_SITE_PACKAGE_DIR], +[AC_REQUIRE([PC_PYTHON_CHECK_SITE_DIR])[]dnl +AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE])]) + + +# PC_PYTHON_CHECK_EXEC_DIR +# ------------------------ +# directory for installing python extension modules (shared libraries) +AC_DEFUN([PC_PYTHON_CHECK_EXEC_DIR], +[AC_REQUIRE([PC_INIT])AC_REQUIRE([PC_PYTHON_CHECK_EXEC_PREFIX])[]dnl + AC_CACHE_CHECK([for Python extension module directory], + [pc_cv_python_exec_dir], + [AC_LANG_PUSH(Python)[]dnl + if test "x$pc_cv_python_exec_prefix" = xNONE + then + pc_py_exec_prefix=$pc_cv_python_prefix + else + pc_py_exec_prefix=$pc_cv_python_exec_prefix + fi + AC_LANG_CONFTEST([ + AC_LANG_PROGRAM([dnl +import sys +from platform import python_implementation +# sysconfig in CPython 2.7 doesn't work in virtualenv +# <https://github.com/pypa/virtualenv/issues/118> +try: + import sysconfig +except: + can_use_sysconfig = False +else: + can_use_sysconfig = True +if can_use_sysconfig: + if python_implementation() == "CPython" and sys.version[[:3]] == '2.7': + can_use_sysconfig = False +if not can_use_sysconfig: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(False, False, prefix='$pc_py__exec_prefix') +else: + sitedir = sysconfig.get_path('purelib', vars={'platbase':'$pc_py_exec_prefix'}) +], [dnl + sys.stdout.write(sitedir) +])]) + pc_cv_python_exec_dir=`$PYTHON conftest.py` + AC_LANG_POP(Python)[]dnl + case $pc_cv_python_exec_dir in + $pc_py_exec_prefix*) + pc__strip_prefix=`echo "$pc_py_exec_prefix" | sed 's|.|.|g'` + pc_cv_python_exec_dir=`echo "$pc_cv_python_exec_dir" | sed "s,^$pc__strip_prefix/,,"` + ;; + *) + case $pc_py_exec_prefix in + /usr|/System*) ;; + *) + pc_cv_python_exec_dir=lib/python$PYTHON_VERSION/site-packages + ;; + esac + ;; + esac + ]) +AC_SUBST([pyexecdir], [\${exec_prefix}/$pc_cv_python_pyexecdir])]) #PY_PYTHON_CHECK_EXEC_LIB_DIR + + +# PC_PYTHON_EXEC_PACKAGE_DIR +# -------------------------- +# $PACKAGE directory under PYTHON_SITE_DIR +AC_DEFUN([PC_PYTHON_EXEC_PACKAGE_DIR], +[AC_REQUIRE([PC_PYTHON_CHECK_EXEC_DIR])[]dnl +AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE])]) + + +## -------------------------------------------- ## +## 4. Looking for specific libs & functionality ## +## -------------------------------------------- ## + + +# PC_PYTHON_CHECK_MODULE(LIBRARY, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# ---------------------------------------------------------------------- +# Macro for checking if a Python library is installed +AC_DEFUN([PC_PYTHON_CHECK_MODULE], +[AC_REQUIRE([PC_INIT])[]dnl +m4_define([pc_python_safe_mod], m4_bpatsubsts($1, [\.], [_])) +AC_CACHE_CHECK([for Python '$1' library], + [[pc_cv_python_module_]pc_python_safe_mod], + [AC_LANG_PUSH(Python)[]dnl + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([dnl +import sys +try: + import $1 +except: + sys.exit(1) +else: + sys.exit(0) +], [])], + [[pc_cv_python_module_]pc_python_safe_mod="yes"], + [[pc_cv_python_module_]pc_python_safe_mod="no"]) + AC_LANG_POP(Python)[]dnl + ]) +AS_IF([test "$[pc_cv_python_module_]pc_python_safe_mod" = "no"], [$3], [$2]) +])# PC_PYTHON_CHECK_MODULE + + +# PC_PYTHON_CHECK_FUNC([LIBRARY], FUNCTION, ARGS, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# --------------------------------------------------------------------------------------- +# Check to see if a given function call, optionally from a module, can +# be successfully called +AC_DEFUN([PC_PYTHON_CHECK_FUNC], +[AC_REQUIRE([PC_INIT])[]dnl +m4_define([pc_python_safe_mod], m4_bpatsubsts($1, [\.], [_])) +AC_CACHE_CHECK([for Python m4_ifnblank($1, '$1.$2()', '$2()') function], + [[pc_cv_python_func_]pc_python_safe_mod[_$2]], + [AC_LANG_PUSH(Python)[]dnl + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([dnl +import sys +m4_ifnblank([$1], [dnl +try: + import $1 +except: + sys.exit(1) +], [])], +[ +m4_ifnblank([$1], [ + try: + $1.$2($3)], [ + try: + $2($3)]) + except: + sys.exit(1) + else: + sys.exit(0) +])], + [[pc_cv_python_func_]pc_python_safe_mod[_$2]="yes"], + [[pc_cv_python_func_]pc_python_safe_mod[_$2]="no"]) + AC_LANG_POP(Python)[]dnl + ]) +AS_IF([test "$[pc_cv_python_func_]pc_python_safe_mod[_$2]" = "no"], [$5], [$4]) +])# PC_PYTHON_CHECK_FUNC diff --git a/mediagoblin.ini b/mediagoblin.ini index bed69737..934858a2 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -11,16 +11,17 @@ email_sender_address = "notice@mediagoblin.example.org" ## Uncomment and change to your DB's appropiate setting. ## Default is a local sqlite db "mediagoblin.db". -# sql_engine = postgresql:///gmg +## Don't forget to run `./bin/gmg dbupdate` after having changed it. +# sql_engine = postgresql:///mediagoblin -# set to false to enable sending notices +# Set to false to enable sending notices email_debug_mode = true # Set to false to disable registrations allow_registration = true -## Uncomment this to turn on video or enable other media types -# media_types = mediagoblin.media_types.image, mediagoblin.media_types.video +# Set to false to disable the ability for users to report offensive content +allow_reporting = true ## Uncomment this to put some user-overriding templates here # local_templates = %(here)s/user_dev/templates/ @@ -31,6 +32,9 @@ allow_registration = true ## install other themes. # theme = airy +## If you want the terms of service displayed, you can uncomment this +# show_tos = true + [storage:queuestore] base_dir = %(here)s/user_dev/media/queue @@ -41,7 +45,11 @@ base_url = /mgoblin_media/ [celery] # Put celery stuff here -# place plugins here---each in their own subsection of [plugins]. see -# documentation for details. +# Place plugins here, each in their own subsection of [plugins]. +# See http://docs.mediagoblin.org/siteadmin/plugins.html for details. [plugins] [[mediagoblin.plugins.geolocation]] +[[mediagoblin.plugins.basic_auth]] +[[mediagoblin.media_types.image]] +#-> uncomment below to enable blog and run ./bin/gmg dbudate +#[[mediagoblin.media_types.blog]] diff --git a/mediagoblin/_version.py b/mediagoblin/_version.py index 8437be8b..9ff2a374 100644 --- a/mediagoblin/_version.py +++ b/mediagoblin/_version.py @@ -23,4 +23,4 @@ # see http://www.python.org/dev/peps/pep-0386/ -__version__ = "0.4.0.dev" +__version__ = "0.6.2.dev" diff --git a/mediagoblin/admin/views.py b/mediagoblin/admin/views.py deleted file mode 100644 index 22ca74a3..00000000 --- a/mediagoblin/admin/views.py +++ /dev/null @@ -1,48 +0,0 @@ -# GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011, 2012 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 werkzeug.exceptions import Forbidden - -from mediagoblin.db.models import MediaEntry -from mediagoblin.decorators import require_active_login -from mediagoblin.tools.response import render_to_response - -@require_active_login -def admin_processing_panel(request): - ''' - Show the global processing panel for this instance - ''' - # TODO: Why not a "require_admin_login" decorator throwing a 403 exception? - if not request.user.is_admin: - raise Forbidden() - - processing_entries = MediaEntry.query.filter_by(state = u'processing').\ - order_by(MediaEntry.created.desc()) - - # Get media entries which have failed to process - failed_entries = MediaEntry.query.filter_by(state = u'failed').\ - order_by(MediaEntry.created.desc()) - - processed_entries = MediaEntry.query.filter_by(state = u'processed').\ - order_by(MediaEntry.created.desc()).limit(10) - - # Render to response - return render_to_response( - request, - 'mediagoblin/admin/panel.html', - {'processing_entries': processing_entries, - 'failed_entries': failed_entries, - 'processed_entries': processed_entries}) diff --git a/mediagoblin/app.py b/mediagoblin/app.py index bf0e0f13..e9177eff 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -29,6 +29,7 @@ from mediagoblin.tools import common, session, translate, template from mediagoblin.tools.response import render_http_exception from mediagoblin.tools.theme import register_themes from mediagoblin.tools import request as mg_request +from mediagoblin.media_types.tools import media_type_warning from mediagoblin.mg_globals import setup_globals from mediagoblin.init.celery import setup_celery_from_config from mediagoblin.init.plugins import setup_plugins @@ -37,6 +38,7 @@ from mediagoblin.init import (get_jinja_loader, get_staticdirector, setup_storage) from mediagoblin.tools.pluginapi import PluginManager, hook_transform from mediagoblin.tools.crypto import setup_crypto +from mediagoblin.auth.tools import check_auth_enabled, no_auth_logout _log = logging.getLogger(__name__) @@ -67,6 +69,8 @@ class MediaGoblinApp(object): # Open and setup the config global_config, app_config = setup_global_and_app_config(config_path) + media_type_warning() + setup_crypto() ########################################## @@ -85,7 +89,7 @@ class MediaGoblinApp(object): setup_plugins() # Set up the database - self.db = setup_database() + self.db = setup_database(app_config['run_migrations']) # Register themes self.theme_registry, self.current_theme = register_themes(app_config) @@ -97,6 +101,11 @@ class MediaGoblinApp(object): PluginManager().get_template_paths() ) + # Check if authentication plugin is enabled and respond accordingly. + self.auth = check_auth_enabled() + if not self.auth: + app_config['allow_comments'] = False + # Set up storage systems self.public_store, self.queue_store = setup_storage() @@ -186,8 +195,12 @@ class MediaGoblinApp(object): request.urlgen = build_proxy + # Log user out if authentication_disabled + no_auth_logout(request) + mg_request.setup_user_in_request(request) + request.controller_name = None try: found_rule, url_values = map_adapter.match(return_rule=True) request.matchdict = url_values @@ -201,6 +214,9 @@ class MediaGoblinApp(object): exc.get_description(environ))(environ, start_response) controller = endpoint_to_controller(found_rule) + # Make a reference to the controller's symbolic name on the request... + # used for lazy context modification + request.controller_name = found_rule.endpoint # pass the request through our meddleware classes try: diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index 621845ba..be5d0eed 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -13,3 +13,32 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +from mediagoblin.tools.pluginapi import hook_handle, hook_runall + + +def get_user(**kwargs): + """ Takes a kwarg such as username and returns a user object """ + return hook_handle("auth_get_user", **kwargs) + + +def create_user(register_form): + results = hook_runall("auth_create_user", register_form) + return results[0] + + +def extra_validation(register_form): + from mediagoblin.auth.tools import basic_extra_validation + + extra_validation_passes = basic_extra_validation(register_form) + if False in hook_runall("auth_extra_validation", register_form): + extra_validation_passes = False + return extra_validation_passes + + +def gen_password_hash(raw_pass, extra_salt=None): + return hook_handle("auth_gen_password_hash", raw_pass, extra_salt) + + +def check_password(raw_pass, stored_hash, extra_salt=None): + return hook_handle("auth_check_password", + raw_pass, stored_hash, extra_salt) diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 2a6abb47..7a688a49 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -25,9 +25,4 @@ auth_routes = [ ('mediagoblin.auth.verify_email', '/verify_email/', 'mediagoblin.auth.views:verify_email'), ('mediagoblin.auth.resend_verification', '/resend_verification/', - 'mediagoblin.auth.views:resend_activation'), - ('mediagoblin.auth.forgot_password', '/forgot_password/', - 'mediagoblin.auth.views:forgot_password'), - ('mediagoblin.auth.verify_forgot_password', - '/forgot_password/verify/', - 'mediagoblin.auth.views:verify_forgot_password')] + 'mediagoblin.auth.views:resend_activation')] diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py new file mode 100644 index 00000000..88716e1c --- /dev/null +++ b/mediagoblin/auth/tools.py @@ -0,0 +1,191 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +import logging +import wtforms +from sqlalchemy import or_ + +from mediagoblin import mg_globals +from mediagoblin.tools.crypto import get_timed_signer_url +from mediagoblin.db.models import User, Privilege +from mediagoblin.tools.mail import (normalize_email, send_email, + email_debug_message) +from mediagoblin.tools.template import render_template +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.tools.pluginapi import hook_handle +from mediagoblin import auth + +_log = logging.getLogger(__name__) + + +def normalize_user_or_email_field(allow_email=True, allow_user=True): + """ + Check if we were passed a field that matches a username and/or email + pattern. + + This is useful for fields that can take either a username or email + address. Use the parameters if you want to only allow a username for + instance""" + message = _(u'Invalid User name or email address.') + nomail_msg = _(u"This field does not take email addresses.") + nouser_msg = _(u"This field requires an email address.") + + def _normalize_field(form, field): + email = u'@' in field.data + if email: # normalize email address casing + if not allow_email: + raise wtforms.ValidationError(nomail_msg) + wtforms.validators.Email()(form, field) + field.data = normalize_email(field.data) + else: # lower case user names + if not allow_user: + raise wtforms.ValidationError(nouser_msg) + wtforms.validators.Length(min=3, max=30)(form, field) + wtforms.validators.Regexp(r'^\w+$')(form, field) + field.data = field.data.lower() + if field.data is None: # should not happen, but be cautious anyway + raise wtforms.ValidationError(message) + return _normalize_field + + +EMAIL_VERIFICATION_TEMPLATE = ( + u"{uri}?" + u"token={verification_key}") + + +def send_verification_email(user, request, email=None, + rendered_email=None): + """ + Send the verification email to users to activate their accounts. + + Args: + - user: a user object + - request: the request + """ + if not email: + email = user.email + + if not rendered_email: + verification_key = get_timed_signer_url('mail_verification_token') \ + .dumps(user.id) + rendered_email = render_template( + request, 'mediagoblin/auth/verification_email.txt', + {'username': user.username, + 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format( + uri=request.urlgen('mediagoblin.auth.verify_email', + qualified=True), + verification_key=verification_key)}) + + # TODO: There is no error handling in place + send_email( + mg_globals.app_config['email_sender_address'], + [email], + # TODO + # Due to the distributed nature of GNU MediaGoblin, we should + # find a way to send some additional information about the + # specific GNU MediaGoblin instance in the subject line. For + # example "GNU MediaGoblin @ Wandborg - [...]". + 'GNU MediaGoblin - Verify your email!', + rendered_email) + + +def basic_extra_validation(register_form, *args): + users_with_username = User.query.filter_by( + username=register_form.username.data).count() + users_with_email = User.query.filter_by( + email=register_form.email.data).count() + + extra_validation_passes = True + + if users_with_username: + register_form.username.errors.append( + _(u'Sorry, a user with that name already exists.')) + extra_validation_passes = False + if users_with_email: + register_form.email.errors.append( + _(u'Sorry, a user with that email address already exists.')) + extra_validation_passes = False + + return extra_validation_passes + + +def register_user(request, register_form): + """ Handle user registration """ + extra_validation_passes = auth.extra_validation(register_form) + + if extra_validation_passes: + # Create the user + user = auth.create_user(register_form) + + # give the user the default privileges + default_privileges = [ + Privilege.query.filter(Privilege.privilege_name==u'commenter').first(), + Privilege.query.filter(Privilege.privilege_name==u'uploader').first(), + Privilege.query.filter(Privilege.privilege_name==u'reporter').first()] + user.all_privileges += default_privileges + user.save() + + # log the user in + request.session['user_id'] = unicode(user.id) + request.session.save() + + # send verification email + email_debug_message(request) + send_verification_email(user, request) + + return user + + return None + + +def check_login_simple(username, password): + user = auth.get_user(username=username) + if not user: + _log.info("User %r not found", username) + hook_handle("auth_fake_login_attempt") + return None + if not auth.check_password(password, user.pw_hash): + _log.warn("Wrong password for %r", username) + return None + _log.info("Logging %r in", username) + return user + + +def check_auth_enabled(): + if not hook_handle('authentication'): + _log.warning('No authentication is enabled') + return False + else: + return True + + +def no_auth_logout(request): + """ + Log out the user if no authentication is enabled, but don't delete + the messages + """ + if not mg_globals.app.auth and 'user_id' in request.session: + del request.session['user_id'] + request.session.save() + + +def create_basic_user(form): + user = User() + user.username = form.username.data + user.email = form.email.data + user.save() + return user diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dc408911..3d132f84 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -14,82 +14,43 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import uuid -import datetime +from itsdangerous import BadSignature from mediagoblin import messages, mg_globals -from mediagoblin.db.models import User +from mediagoblin.db.models import User, Privilege +from mediagoblin.tools.crypto import get_timed_signer_url +from mediagoblin.decorators import auth_enabled, allow_registration from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ -from mediagoblin.auth import lib as auth_lib -from mediagoblin.auth import forms as auth_forms -from mediagoblin.auth.lib import send_verification_email, \ - send_fp_verification_email -from sqlalchemy import or_ - -def email_debug_message(request): - """ - If the server is running in email debug mode (which is - the current default), give a debug message to the user - so that they have an idea where to find their email. - """ - if mg_globals.app_config['email_debug_mode']: - # DEBUG message, no need to translate - messages.add_message(request, messages.DEBUG, - u"This instance is running in email debug mode. " - u"The email will be on the console of the server process.") +from mediagoblin.tools.mail import email_debug_message +from mediagoblin.tools.pluginapi import hook_handle +from mediagoblin.auth.tools import (send_verification_email, register_user, + check_login_simple) +@allow_registration +@auth_enabled def register(request): """The registration view. Note that usernames will always be lowercased. Email domains are lowercased while the first part remains case-sensitive. """ - # Redirects to indexpage if registrations are disabled - if not mg_globals.app_config["allow_registration"]: - messages.add_message( - request, - messages.WARNING, - _('Sorry, registration is disabled on this instance.')) - return redirect(request, "index") + if 'pass_auth' not in request.template_env.globals: + redirect_name = hook_handle('auth_no_pass_redirect') + if redirect_name: + return redirect(request, 'mediagoblin.plugins.{0}.register'.format( + redirect_name)) + else: + return redirect(request, 'index') - register_form = auth_forms.RegistrationForm(request.form) + register_form = hook_handle("auth_get_registration_form", request) if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already - users_with_username = User.query.filter_by(username=register_form.data['username']).count() - users_with_email = User.query.filter_by(email=register_form.data['email']).count() - - extra_validation_passes = True - - if users_with_username: - register_form.username.errors.append( - _(u'Sorry, a user with that name already exists.')) - extra_validation_passes = False - if users_with_email: - register_form.email.errors.append( - _(u'Sorry, a user with that email address already exists.')) - extra_validation_passes = False - - if extra_validation_passes: - # Create the user - user = User() - user.username = register_form.data['username'] - user.email = register_form.data['email'] - user.pw_hash = auth_lib.bcrypt_gen_password_hash( - register_form.password.data) - user.verification_key = unicode(uuid.uuid4()) - user.save() - - # log the user in - request.session['user_id'] = unicode(user.id) - request.session.save() - - # send verification email - email_debug_message(request) - send_verification_email(user, request) + user = register_user(request, register_form) + if user: # redirect the user to their homepage... there will be a # message waiting for them to verify their email return redirect( @@ -99,33 +60,39 @@ def register(request): return render_to_response( request, 'mediagoblin/auth/register.html', - {'register_form': register_form}) + {'register_form': register_form, + 'post_url': request.urlgen('mediagoblin.auth.register')}) +@auth_enabled def login(request): """ MediaGoblin login view. If you provide the POST with 'next', it'll redirect to that view. """ - login_form = auth_forms.LoginForm(request.form) + if 'pass_auth' not in request.template_env.globals: + redirect_name = hook_handle('auth_no_pass_redirect') + if redirect_name: + return redirect(request, 'mediagoblin.plugins.{0}.login'.format( + redirect_name)) + else: + return redirect(request, 'index') + + login_form = hook_handle("auth_get_login_form", request) login_failed = False if request.method == 'POST': - - username = login_form.data['username'] + username = login_form.username.data if login_form.validate(): - user = User.query.filter( - or_( - User.username == username, - User.email == username, - - )).first() + user = check_login_simple(username, login_form.password.data) - if user and user.check_login(login_form.password.data): + if user: # set up login in session + if login_form.stay_logged_in.data: + request.session['stay_logged_in'] = True request.session['user_id'] = unicode(user.id) request.session.save() @@ -134,10 +101,6 @@ def login(request): else: return redirect(request, "index") - # Some failure during login occured if we are here! - # Prevent detecting who's on this system by testing login - # attempt timings - auth_lib.fake_login_attempt() login_failed = True return render_to_response( @@ -146,6 +109,7 @@ def login(request): {'login_form': login_form, 'next': request.GET.get('next') or request.form.get('next'), 'login_failed': login_failed, + 'post_url': request.urlgen('mediagoblin.auth.login'), 'allow_registration': mg_globals.app_config["allow_registration"]}) @@ -164,15 +128,30 @@ def verify_email(request): you are lucky :) """ # If we don't have userid and token parameters, we can't do anything; 404 - if not 'userid' in request.GET or not 'token' in request.GET: + if not 'token' in request.GET: return render_404(request) - user = User.query.filter_by(id=request.args['userid']).first() + # Catch error if token is faked or expired + try: + token = get_timed_signer_url("mail_verification_token") \ + .loads(request.GET['token'], max_age=10*24*3600) + except BadSignature: + messages.add_message( + request, + messages.ERROR, + _('The verification key or user id is incorrect.')) - if user and user.verification_key == unicode(request.GET['token']): - user.status = u'active' - user.email_verified = True + return redirect( + request, + 'index') + + user = User.query.filter_by(id=int(token)).first() + + if user and user.has_privilege(u'active') is False: user.verification_key = None + user.all_privileges.append( + Privilege.query.filter( + Privilege.privilege_name==u'active').first()) user.save() @@ -207,7 +186,7 @@ def resend_activation(request): return redirect(request, 'mediagoblin.auth.login') - if request.user.email_verified: + if request.user.has_privilege(u'active'): messages.add_message( request, messages.ERROR, @@ -215,9 +194,6 @@ def resend_activation(request): return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username']) - request.user.verification_key = unicode(uuid.uuid4()) - request.user.save() - email_debug_message(request) send_verification_email(request.user, request) @@ -228,141 +204,3 @@ def resend_activation(request): return redirect( request, 'mediagoblin.user_pages.user_home', user=request.user.username) - - -def forgot_password(request): - """ - Forgot password view - - Sends an email with an url to renew forgotten password. - Use GET querystring parameter 'username' to pre-populate the input field - """ - fp_form = auth_forms.ForgotPassForm(request.form, - username=request.args.get('username')) - - if not (request.method == 'POST' and fp_form.validate()): - # Either GET request, or invalid form submitted. Display the template - return render_to_response(request, - 'mediagoblin/auth/forgot_password.html', {'fp_form': fp_form}) - - # If we are here: method == POST and form is valid. username casing - # has been sanitized. Store if a user was found by email. We should - # not reveal if the operation was successful then as we don't want to - # leak if an email address exists in the system. - found_by_email = '@' in fp_form.username.data - - if found_by_email: - user = User.query.filter_by( - email = fp_form.username.data).first() - # Don't reveal success in case the lookup happened by email address. - success_message=_("If that email address (case sensitive!) is " - "registered an email has been sent with instructions " - "on how to change your password.") - - else: # found by username - user = User.query.filter_by( - username = fp_form.username.data).first() - - if user is None: - messages.add_message(request, - messages.WARNING, - _("Couldn't find someone with that username.")) - return redirect(request, 'mediagoblin.auth.forgot_password') - - success_message=_("An email has been sent with instructions " - "on how to change your password.") - - if user and not(user.email_verified and user.status == 'active'): - # Don't send reminder because user is inactive or has no verified email - messages.add_message(request, - messages.WARNING, - _("Could not send password recovery email as your username is in" - "active or your account's email address has not been verified.")) - - return redirect(request, 'mediagoblin.user_pages.user_home', - user=user.username) - - # SUCCESS. Send reminder and return to login page - if user: - user.fp_verification_key = unicode(uuid.uuid4()) - user.fp_token_expire = datetime.datetime.now() + \ - datetime.timedelta(days=10) - user.save() - - email_debug_message(request) - send_fp_verification_email(user, request) - - messages.add_message(request, messages.INFO, success_message) - return redirect(request, 'mediagoblin.auth.login') - - -def verify_forgot_password(request): - """ - Check the forgot-password verification and possibly let the user - change their password because of it. - """ - # get form data variables, and specifically check for presence of token - formdata = _process_for_token(request) - if not formdata['has_userid_and_token']: - return render_404(request) - - formdata_token = formdata['vars']['token'] - formdata_userid = formdata['vars']['userid'] - formdata_vars = formdata['vars'] - - # check if it's a valid user id - user = User.query.filter_by(id=formdata_userid).first() - if not user: - 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')): - - cp_form = auth_forms.ChangePassForm(formdata_vars) - - if request.method == 'POST' and cp_form.validate(): - user.pw_hash = auth_lib.bcrypt_gen_password_hash( - cp_form.password.data) - user.fp_verification_key = None - user.fp_token_expire = None - user.save() - - messages.add_message( - request, - messages.INFO, - _("You can now log in using your new password.")) - return redirect(request, 'mediagoblin.auth.login') - else: - return render_to_response( - request, - 'mediagoblin/auth/change_fp.html', - {'cp_form': cp_form}) - - # in case there is a valid id but no user with that id in the db - # or the token expired - else: - return render_404(request) - - -def _process_for_token(request): - """ - Checks for tokens in formdata without prior knowledge of request method - - For now, returns whether the userid and token formdata variables exist, and - the formdata variables in a hash. Perhaps an object is warranted? - """ - # retrieve the formdata variables - if request.method == 'GET': - formdata_vars = request.GET - else: - formdata_vars = request.form - - formdata = { - 'vars': formdata_vars, - 'has_userid_and_token': - 'userid' in formdata_vars and 'token' in formdata_vars} - - return formdata diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index b7c6f29a..cc1ac637 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -5,12 +5,13 @@ html_title = string(default="GNU MediaGoblin") # link to source for this MediaGoblin site source_link = string(default="https://gitorious.org/mediagoblin/mediagoblin") -# Enabled media types -media_types = string_list(default=list("mediagoblin.media_types.image")) - # database stuff sql_engine = string(default="sqlite:///%(here)s/mediagoblin.db") +# This flag is used during testing to allow use of in-memory SQLite +# databases. It is not recommended to be used on a running instance. +run_migrations = boolean(default=False) + # Where temporary files used in processing and etc are kept workbench_path = string(default="%(here)s/user_dev/media/workbench") @@ -22,9 +23,10 @@ direct_remote_path = string(default="/mgoblin_static/") # set to false to enable sending notices email_debug_mode = boolean(default=True) +email_smtp_use_ssl = boolean(default=False) email_sender_address = string(default="notice@mediagoblin.example.org") email_smtp_host = string(default='') -email_smtp_port = integer(default=25) +email_smtp_port = integer(default=0) email_smtp_user = string(default=None) email_smtp_pass = string(default=None) @@ -34,9 +36,20 @@ allow_registration = boolean(default=True) # tag parsing tags_max_length = integer(default=255) +# Enable/disable comments +allow_comments = boolean(default=True) + # Whether comments are ascending or descending comments_ascending = boolean(default=True) +# Enable/disable reporting +allow_reporting = boolean(default=True) + +# Enable/disable terms of service +# ... Note: you can override the terms of service template on a +# per-site basis... +show_tos = boolean(default=False) + # By default not set, but you might want something like: # "%(here)s/user_dev/templates/" local_templates = string() @@ -58,6 +71,7 @@ csrf_cookie_name = string(default='mediagoblin_csrftoken') push_urls = string_list(default=list()) exif_visible = boolean(default=False) +original_date_visible = boolean(default=False) # Theming stuff theme_install_dir = string(default="%(here)s/user_dev/themes/") @@ -65,6 +79,22 @@ theme_web_path = string(default="/theme_static/") theme_linked_assets_dir = string(default="%(here)s/user_dev/theme_static/") theme = string() +# plugin default assets directory +plugin_web_path = string(default="/plugin_static/") +plugin_linked_assets_dir = string(default="%(here)s/user_dev/plugin_static/") + +# Default user upload limit (in Mb) +upload_limit = integer(default=None) + +# Max file size (in Mb) +max_file_size = integer(default=None) + +[jinja2] +# Jinja2 supports more directives than the minimum required by mediagoblin. +# This setting allows users creating custom templates to specify a list of +# additional extensions they want to use. example value: +# extensions = jinja2.ext.loopcontrols , jinja2.ext.with_ +extensions = string_list(default=list()) [storage:publicstore] storage_class = string(default="mediagoblin.storage.filestorage:BasicFileStorage") @@ -88,47 +118,6 @@ max_height = integer(default=640) max_width = integer(default=180) max_height = integer(default=180) -[media_type:mediagoblin.media_types.image] -# One of BICUBIC, BILINEAR, NEAREST, ANTIALIAS -resize_filter = string(default="ANTIALIAS") -#level of compression used when resizing images -quality = integer(default=90) - -[media_type:mediagoblin.media_types.video] -# Should we keep the original file? -keep_original = boolean(default=False) - -# 0 means autodetect, autodetect means number_of_CPUs - 1 -vp8_threads = integer(default=0) -# Range: 0..10 -vp8_quality = integer(default=8) -# Range: -0.1..1 -vorbis_quality = float(default=0.3) - -# Autoplay the video when page is loaded? -auto_play = boolean(default=True) - -[[skip_transcode]] -mime_types = string_list(default=list("video/webm")) -container_formats = string_list(default=list("Matroska")) -video_codecs = string_list(default=list("VP8 video")) -audio_codecs = string_list(default=list("Vorbis")) -dimensions_match = boolean(default=True) - -[media_type:mediagoblin.media_types.audio] -keep_original = boolean(default=True) -# vorbisenc quality -quality = float(default=0.3) -create_spectrogram = boolean(default=True) -spectrogram_fft_size = integer(default=4096) - -[media_type:mediagoblin.media_types.ascii] -thumbnail_font = string(default=None) - -[media_type:mediagoblin.media_types.pdf] -pdf_js = boolean(default=False) - - [celery] # default result stuff CELERY_RESULT_BACKEND = string(default="database") @@ -136,7 +125,7 @@ CELERY_RESULT_DBURI = string(default="sqlite:///%(here)s/celery.db") # default kombu stuff BROKER_TRANSPORT = string(default="sqlalchemy") -BROKER_HOST = string(default="sqlite:///%(here)s/kombu.db") +BROKER_URL = string(default="sqlite:///%(here)s/kombu.db") # known booleans CELERY_RESULT_PERSISTENT = boolean() diff --git a/mediagoblin/db/base.py b/mediagoblin/db/base.py index 699a503a..c0cefdc2 100644 --- a/mediagoblin/db/base.py +++ b/mediagoblin/db/base.py @@ -24,18 +24,6 @@ Session = scoped_session(sessionmaker()) class GMGTableBase(object): query = Session.query_property() - @classmethod - def find(cls, query_dict): - return cls.query.filter_by(**query_dict) - - @classmethod - def find_one(cls, query_dict): - return cls.query.filter_by(**query_dict).first() - - @classmethod - def one(cls, query_dict): - return cls.find(query_dict).one() - def get(self, key): return getattr(self, key) diff --git a/mediagoblin/db/extratypes.py b/mediagoblin/db/extratypes.py index f2304af0..8e04d58d 100644 --- a/mediagoblin/db/extratypes.py +++ b/mediagoblin/db/extratypes.py @@ -15,6 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. +from sqlalchemy.ext.mutable import Mutable from sqlalchemy.types import TypeDecorator, Unicode, TEXT import json @@ -38,7 +39,7 @@ class PathTupleWithSlashes(TypeDecorator): return value -# The following class and only this one class is in very +# The following two classes and only these two classes is in very # large parts based on example code from sqlalchemy. # # The original copyright notice and license follows: @@ -61,3 +62,30 @@ class JSONEncoded(TypeDecorator): if value is not None: value = json.loads(value) return value + + +class MutationDict(Mutable, dict): + @classmethod + def coerce(cls, key, value): + "Convert plain dictionaries to MutationDict." + + if not isinstance(value, MutationDict): + if isinstance(value, dict): + return MutationDict(value) + + # this call will raise ValueError + return Mutable.coerce(key, value) + else: + return value + + def __setitem__(self, key, value): + "Detect dictionary set events and emit change events." + + dict.__setitem__(self, key, value) + self.changed() + + def __delitem__(self, key): + "Detect dictionary del events and emit change events." + + dict.__delitem__(self, key) + self.changed() diff --git a/mediagoblin/db/migration_tools.py b/mediagoblin/db/migration_tools.py index c0c7e998..e39070c3 100644 --- a/mediagoblin/db/migration_tools.py +++ b/mediagoblin/db/migration_tools.py @@ -16,6 +16,7 @@ from mediagoblin.tools.common import simple_printer from sqlalchemy import Table +from sqlalchemy.sql import select class TableAlreadyExists(Exception): pass @@ -29,7 +30,7 @@ class MigrationManager(object): to the latest migrations, etc. """ - def __init__(self, name, models, migration_registry, session, + def __init__(self, name, models, foundations, migration_registry, session, printer=simple_printer): """ Args: @@ -40,6 +41,7 @@ class MigrationManager(object): """ self.name = unicode(name) self.models = models + self.foundations = foundations self.session = session self.migration_registry = migration_registry self._sorted_migrations = None @@ -140,6 +142,18 @@ class MigrationManager(object): self.session.bind, tables=[model.__table__ for model in self.models]) + def populate_table_foundations(self): + """ + Create the table foundations (default rows) as layed out in FOUNDATIONS + in mediagoblin.db.models + """ + for Model, rows in self.foundations.items(): + self.printer(u' + Laying foundations for %s table\n' % + (Model.__name__)) + for parameters in rows: + new_row = Model(**parameters) + self.session.add(new_row) + def create_new_migration_record(self): """ Create a new migration record for this migration set @@ -175,8 +189,7 @@ class MigrationManager(object): if self.name == u'__main__': return u"main mediagoblin tables" else: - # TODO: Use the friendlier media manager "human readable" name - return u'media type "%s"' % self.name + return u'plugin "%s"' % self.name def init_or_migrate(self): """ @@ -203,9 +216,9 @@ class MigrationManager(object): self.init_tables() # auto-set at latest migration number - self.create_new_migration_record() - + self.create_new_migration_record() self.printer(u"done.\n") + self.populate_table_foundations() self.set_current_migration() return u'inited' @@ -274,3 +287,35 @@ def inspect_table(metadata, table_name): """Simple helper to get a ref to an already existing table""" return Table(table_name, metadata, autoload=True, autoload_with=metadata.bind) + +def replace_table_hack(db, old_table, replacement_table): + """ + A function to fully replace a current table with a new one for migrati- + -ons. This is necessary because some changes are made tricky in some situa- + -tion, for example, dropping a boolean column in sqlite is impossible w/o + this method + + :param old_table A ref to the old table, gotten through + inspect_table + + :param replacement_table A ref to the new table, gotten through + inspect_table + + Users are encouraged to sqlalchemy-migrate replace table solutions, unless + that is not possible... in which case, this solution works, + at least for sqlite. + """ + surviving_columns = replacement_table.columns.keys() + old_table_name = old_table.name + for row in db.execute(select( + [column for column in old_table.columns + if column.name in surviving_columns])): + + db.execute(replacement_table.insert().values(**row)) + db.commit() + + old_table.drop() + db.commit() + + replacement_table.rename(old_table_name) + db.commit() diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 2c553396..426080a2 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -19,14 +19,18 @@ import uuid from sqlalchemy import (MetaData, Table, Column, Boolean, SmallInteger, Integer, Unicode, UnicodeText, DateTime, - ForeignKey) + ForeignKey, Date) from sqlalchemy.exc import ProgrammingError from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.sql import and_ from migrate.changeset.constraint import UniqueConstraint -from mediagoblin.db.migration_tools import RegisterMigration, inspect_table -from mediagoblin.db.models import MediaEntry, Collection, User + +from mediagoblin.db.extratypes import JSONEncoded, MutationDict +from mediagoblin.db.migration_tools import ( + RegisterMigration, inspect_table, replace_table_hack) +from mediagoblin.db.models import (MediaEntry, Collection, MediaComment, User, + Privilege) MIGRATIONS = {} @@ -287,3 +291,432 @@ def unique_collections_slug(db): constraint.create() db.commit() + +@RegisterMigration(11, MIGRATIONS) +def drop_token_related_User_columns(db): + """ + Drop unneeded columns from the User table after switching to using + itsdangerous tokens for email and forgot password verification. + """ + metadata = MetaData(bind=db.bind) + user_table = inspect_table(metadata, 'core__users') + + verification_key = user_table.columns['verification_key'] + fp_verification_key = user_table.columns['fp_verification_key'] + fp_token_expire = user_table.columns['fp_token_expire'] + + verification_key.drop() + fp_verification_key.drop() + fp_token_expire.drop() + + db.commit() + + +class CommentSubscription_v0(declarative_base()): + __tablename__ = 'core__comment_subscriptions' + id = Column(Integer, primary_key=True) + + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + + media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False) + + user_id = Column(Integer, ForeignKey(User.id), nullable=False) + + notify = Column(Boolean, nullable=False, default=True) + send_email = Column(Boolean, nullable=False, default=True) + + +class Notification_v0(declarative_base()): + __tablename__ = 'core__notifications' + id = Column(Integer, primary_key=True) + type = Column(Unicode) + + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + + user_id = Column(Integer, ForeignKey(User.id), nullable=False, + index=True) + seen = Column(Boolean, default=lambda: False, index=True) + + +class CommentNotification_v0(Notification_v0): + __tablename__ = 'core__comment_notifications' + id = Column(Integer, ForeignKey(Notification_v0.id), primary_key=True) + + subject_id = Column(Integer, ForeignKey(MediaComment.id)) + + +class ProcessingNotification_v0(Notification_v0): + __tablename__ = 'core__processing_notifications' + + id = Column(Integer, ForeignKey(Notification_v0.id), primary_key=True) + + subject_id = Column(Integer, ForeignKey(MediaEntry.id)) + + +@RegisterMigration(12, MIGRATIONS) +def add_new_notification_tables(db): + metadata = MetaData(bind=db.bind) + + user_table = inspect_table(metadata, 'core__users') + mediaentry_table = inspect_table(metadata, 'core__media_entries') + mediacomment_table = inspect_table(metadata, 'core__media_comments') + + CommentSubscription_v0.__table__.create(db.bind) + + Notification_v0.__table__.create(db.bind) + CommentNotification_v0.__table__.create(db.bind) + ProcessingNotification_v0.__table__.create(db.bind) + + db.commit() + + +@RegisterMigration(13, MIGRATIONS) +def pw_hash_nullable(db): + """Make pw_hash column nullable""" + metadata = MetaData(bind=db.bind) + user_table = inspect_table(metadata, "core__users") + + user_table.c.pw_hash.alter(nullable=True) + + # sqlite+sqlalchemy seems to drop this constraint during the + # migration, so we add it back here for now a bit manually. + if db.bind.url.drivername == 'sqlite': + constraint = UniqueConstraint('username', table=user_table) + constraint.create() + + db.commit() + + +# oauth1 migrations +class Client_v0(declarative_base()): + """ + Model representing a client - Used for API Auth + """ + __tablename__ = "core__clients" + + id = Column(Unicode, nullable=True, primary_key=True) + secret = Column(Unicode, nullable=False) + expirey = Column(DateTime, nullable=True) + application_type = Column(Unicode, nullable=False) + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + updated = Column(DateTime, nullable=False, default=datetime.datetime.now) + + # optional stuff + redirect_uri = Column(JSONEncoded, nullable=True) + logo_url = Column(Unicode, nullable=True) + application_name = Column(Unicode, nullable=True) + contacts = Column(JSONEncoded, nullable=True) + + def __repr__(self): + if self.application_name: + return "<Client {0} - {1}>".format(self.application_name, self.id) + else: + return "<Client {0}>".format(self.id) + +class RequestToken_v0(declarative_base()): + """ + Model for representing the request tokens + """ + __tablename__ = "core__request_tokens" + + token = Column(Unicode, primary_key=True) + secret = Column(Unicode, nullable=False) + client = Column(Unicode, ForeignKey(Client_v0.id)) + user = Column(Integer, ForeignKey(User.id), nullable=True) + used = Column(Boolean, default=False) + authenticated = Column(Boolean, default=False) + verifier = Column(Unicode, nullable=True) + callback = Column(Unicode, nullable=False, default=u"oob") + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + updated = Column(DateTime, nullable=False, default=datetime.datetime.now) + +class AccessToken_v0(declarative_base()): + """ + Model for representing the access tokens + """ + __tablename__ = "core__access_tokens" + + token = Column(Unicode, nullable=False, primary_key=True) + secret = Column(Unicode, nullable=False) + user = Column(Integer, ForeignKey(User.id)) + request_token = Column(Unicode, ForeignKey(RequestToken_v0.token)) + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + updated = Column(DateTime, nullable=False, default=datetime.datetime.now) + + +class NonceTimestamp_v0(declarative_base()): + """ + A place the timestamp and nonce can be stored - this is for OAuth1 + """ + __tablename__ = "core__nonce_timestamps" + + nonce = Column(Unicode, nullable=False, primary_key=True) + timestamp = Column(DateTime, nullable=False, primary_key=True) + + +@RegisterMigration(14, MIGRATIONS) +def create_oauth1_tables(db): + """ Creates the OAuth1 tables """ + + Client_v0.__table__.create(db.bind) + RequestToken_v0.__table__.create(db.bind) + AccessToken_v0.__table__.create(db.bind) + NonceTimestamp_v0.__table__.create(db.bind) + + db.commit() + + +@RegisterMigration(15, MIGRATIONS) +def wants_notifications(db): + """Add a wants_notifications field to User model""" + metadata = MetaData(bind=db.bind) + user_table = inspect_table(metadata, "core__users") + col = Column('wants_notifications', Boolean, default=True) + col.create(user_table) + db.commit() + + + +@RegisterMigration(16, MIGRATIONS) +def upload_limits(db): + """Add user upload limit columns""" + metadata = MetaData(bind=db.bind) + + user_table = inspect_table(metadata, 'core__users') + media_entry_table = inspect_table(metadata, 'core__media_entries') + + col = Column('uploaded', Integer, default=0) + col.create(user_table) + + col = Column('upload_limit', Integer) + col.create(user_table) + + col = Column('file_size', Integer, default=0) + col.create(media_entry_table) + + db.commit() + + +@RegisterMigration(17, MIGRATIONS) +def add_file_metadata(db): + """Add file_metadata to MediaFile""" + metadata = MetaData(bind=db.bind) + media_file_table = inspect_table(metadata, "core__mediafiles") + + col = Column('file_metadata', MutationDict.as_mutable(JSONEncoded)) + col.create(media_file_table) + + db.commit() + +################### +# Moderation tables +################### + +class ReportBase_v0(declarative_base()): + __tablename__ = 'core__reports' + id = Column(Integer, primary_key=True) + reporter_id = Column(Integer, ForeignKey(User.id), nullable=False) + report_content = Column(UnicodeText) + reported_user_id = Column(Integer, ForeignKey(User.id), nullable=False) + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + discriminator = Column('type', Unicode(50)) + resolver_id = Column(Integer, ForeignKey(User.id)) + resolved = Column(DateTime) + result = Column(UnicodeText) + __mapper_args__ = {'polymorphic_on': discriminator} + + +class CommentReport_v0(ReportBase_v0): + __tablename__ = 'core__reports_on_comments' + __mapper_args__ = {'polymorphic_identity': 'comment_report'} + + id = Column('id',Integer, ForeignKey('core__reports.id'), + primary_key=True) + comment_id = Column(Integer, ForeignKey(MediaComment.id), nullable=True) + + +class MediaReport_v0(ReportBase_v0): + __tablename__ = 'core__reports_on_media' + __mapper_args__ = {'polymorphic_identity': 'media_report'} + + id = Column('id',Integer, ForeignKey('core__reports.id'), primary_key=True) + media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=True) + + +class UserBan_v0(declarative_base()): + __tablename__ = 'core__user_bans' + user_id = Column(Integer, ForeignKey(User.id), nullable=False, + primary_key=True) + expiration_date = Column(Date) + reason = Column(UnicodeText, nullable=False) + + +class Privilege_v0(declarative_base()): + __tablename__ = 'core__privileges' + id = Column(Integer, nullable=False, primary_key=True, unique=True) + privilege_name = Column(Unicode, nullable=False, unique=True) + + +class PrivilegeUserAssociation_v0(declarative_base()): + __tablename__ = 'core__privileges_users' + privilege_id = Column( + 'core__privilege_id', + Integer, + ForeignKey(User.id), + primary_key=True) + user_id = Column( + 'core__user_id', + Integer, + ForeignKey(Privilege.id), + primary_key=True) + + +PRIVILEGE_FOUNDATIONS_v0 = [{'privilege_name':u'admin'}, + {'privilege_name':u'moderator'}, + {'privilege_name':u'uploader'}, + {'privilege_name':u'reporter'}, + {'privilege_name':u'commenter'}, + {'privilege_name':u'active'}] + + +# vR1 stands for "version Rename 1". This only exists because we need +# to deal with dropping some booleans and it's otherwise impossible +# with sqlite. + +class User_vR1(declarative_base()): + __tablename__ = 'rename__users' + id = Column(Integer, primary_key=True) + username = Column(Unicode, nullable=False, unique=True) + email = Column(Unicode, nullable=False) + pw_hash = Column(Unicode) + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + wants_comment_notification = Column(Boolean, default=True) + wants_notifications = Column(Boolean, default=True) + license_preference = Column(Unicode) + url = Column(Unicode) + bio = Column(UnicodeText) # ?? + uploaded = Column(Integer, default=0) + upload_limit = Column(Integer) + + +@RegisterMigration(18, MIGRATIONS) +def create_moderation_tables(db): + + # First, we will create the new tables in the database. + #-------------------------------------------------------------------------- + ReportBase_v0.__table__.create(db.bind) + CommentReport_v0.__table__.create(db.bind) + MediaReport_v0.__table__.create(db.bind) + UserBan_v0.__table__.create(db.bind) + Privilege_v0.__table__.create(db.bind) + PrivilegeUserAssociation_v0.__table__.create(db.bind) + + db.commit() + + # Then initialize the tables that we will later use + #-------------------------------------------------------------------------- + metadata = MetaData(bind=db.bind) + privileges_table= inspect_table(metadata, "core__privileges") + user_table = inspect_table(metadata, 'core__users') + user_privilege_assoc = inspect_table( + metadata, 'core__privileges_users') + + # This section initializes the default Privilege foundations, that + # would be created through the FOUNDATIONS system in a new instance + #-------------------------------------------------------------------------- + for parameters in PRIVILEGE_FOUNDATIONS_v0: + db.execute(privileges_table.insert().values(**parameters)) + + db.commit() + + # This next section takes the information from the old is_admin and status + # columns and converts those to the new privilege system + #-------------------------------------------------------------------------- + admin_users_ids, active_users_ids, inactive_users_ids = ( + db.execute( + user_table.select().where( + user_table.c.is_admin==True)).fetchall(), + db.execute( + user_table.select().where( + user_table.c.is_admin==False).where( + user_table.c.status==u"active")).fetchall(), + db.execute( + user_table.select().where( + user_table.c.is_admin==False).where( + user_table.c.status!=u"active")).fetchall()) + + # Get the ids for each of the privileges so we can reference them ~~~~~~~~~ + (admin_privilege_id, uploader_privilege_id, + reporter_privilege_id, commenter_privilege_id, + active_privilege_id) = [ + db.execute(privileges_table.select().where( + privileges_table.c.privilege_name==privilege_name)).first()['id'] + for privilege_name in + [u"admin",u"uploader",u"reporter",u"commenter",u"active"] + ] + + # Give each user the appopriate privileges depending whether they are an + # admin, an active user or an inactive user ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + for admin_user in admin_users_ids: + admin_user_id = admin_user['id'] + for privilege_id in [admin_privilege_id, uploader_privilege_id, + reporter_privilege_id, commenter_privilege_id, + active_privilege_id]: + db.execute(user_privilege_assoc.insert().values( + core__privilege_id=admin_user_id, + core__user_id=privilege_id)) + + for active_user in active_users_ids: + active_user_id = active_user['id'] + for privilege_id in [uploader_privilege_id, reporter_privilege_id, + commenter_privilege_id, active_privilege_id]: + db.execute(user_privilege_assoc.insert().values( + core__privilege_id=active_user_id, + core__user_id=privilege_id)) + + for inactive_user in inactive_users_ids: + inactive_user_id = inactive_user['id'] + for privilege_id in [uploader_privilege_id, reporter_privilege_id, + commenter_privilege_id]: + db.execute(user_privilege_assoc.insert().values( + core__privilege_id=inactive_user_id, + core__user_id=privilege_id)) + + db.commit() + + # And then, once the information is taken from is_admin & status columns + # we drop all of the vestigial columns from the User table. + #-------------------------------------------------------------------------- + if db.bind.url.drivername == 'sqlite': + # SQLite has some issues that make it *impossible* to drop boolean + # columns. So, the following code is a very hacky workaround which + # makes it possible. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + User_vR1.__table__.create(db.bind) + db.commit() + new_user_table = inspect_table(metadata, 'rename__users') + replace_table_hack(db, user_table, new_user_table) + else: + # If the db is not run using SQLite, this process is much simpler ~~~~~ + + status = user_table.columns['status'] + email_verified = user_table.columns['email_verified'] + is_admin = user_table.columns['is_admin'] + status.drop() + email_verified.drop() + is_admin.drop() + + db.commit() +@RegisterMigration(19, MIGRATIONS) +def drop_MediaEntry_collected(db): + """ + Drop unused MediaEntry.collected column + """ + metadata = MetaData(bind=db.bind) + + media_collected= inspect_table(metadata, 'core__media_entries') + media_collected = media_collected.columns['collected'] + + media_collected.drop() + + db.commit() diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index 388bac89..25ce6642 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -28,30 +28,24 @@ real objects. """ import uuid +import re +from datetime import datetime from werkzeug.utils import cached_property from mediagoblin import mg_globals -from mediagoblin.auth import lib as auth_lib -from mediagoblin.media_types import get_media_managers, FileTypeNotSupported +from mediagoblin.media_types import FileTypeNotSupported from mediagoblin.tools import common, licenses +from mediagoblin.tools.pluginapi import hook_handle from mediagoblin.tools.text import cleaned_markdown_conversion from mediagoblin.tools.url import slugify class UserMixin(object): - def check_login(self, password): - """ - See if a user can login with this password - """ - return auth_lib.bcrypt_check_password( - password, self.pw_hash) - @property def bio_html(self): return cleaned_markdown_conversion(self.bio) - class GenerateSlugMixin(object): """ Mixin to add a generate_slug method to objects. @@ -208,14 +202,14 @@ class MediaEntryMixin(GenerateSlugMixin): Raises FileTypeNotSupported in case no such manager is enabled """ - # TODO, we should be able to make this a simple lookup rather - # than iterating through all media managers. - for media_type, manager in get_media_managers(): - if media_type == self.media_type: - return manager(self) + manager = hook_handle(('media_manager', self.media_type)) + if manager: + return manager(self) + # Not found? Then raise an error raise FileTypeNotSupported( - "MediaManager not in enabled types. Check media_types in config?") + "MediaManager not in enabled types. Check media_type plugins are" + " enabled in config?") def get_fail_exception(self): """ @@ -229,15 +223,60 @@ class MediaEntryMixin(GenerateSlugMixin): return licenses.get_license_by_url(self.license or "") def exif_display_iter(self): - from mediagoblin.tools.exif import USEFUL_TAGS + if not self.media_data: + return + exif_all = self.media_data.get("exif_all") + for key in exif_all: + label = re.sub('(.)([A-Z][a-z]+)', r'\1 \2', key) + yield label.replace('EXIF', '').replace('Image', ''), exif_all[key] + + def exif_display_data_short(self): + """Display a very short practical version of exif info""" if not self.media_data: return + exif_all = self.media_data.get("exif_all") - for key in USEFUL_TAGS: - if key in exif_all: - yield key, exif_all[key] + exif_short = {} + + if 'Image DateTimeOriginal' in exif_all: + # format date taken + takendate = datetime.datetime.strptime( + exif_all['Image DateTimeOriginal']['printable'], + '%Y:%m:%d %H:%M:%S').date() + taken = takendate.strftime('%B %d %Y') + + exif_short.update({'Date Taken': taken}) + + aperture = None + if 'EXIF FNumber' in exif_all: + fnum = str(exif_all['EXIF FNumber']['printable']).split('/') + + # calculate aperture + if len(fnum) == 2: + aperture = "f/%.1f" % (float(fnum[0])/float(fnum[1])) + elif fnum[0] != 'None': + aperture = "f/%s" % (fnum[0]) + + if aperture: + exif_short.update({'Aperture': aperture}) + + short_keys = [ + ('Camera', 'Image Model', None), + ('Exposure', 'EXIF ExposureTime', lambda x: '%s sec' % x), + ('ISO Speed', 'EXIF ISOSpeedRatings', None), + ('Focal Length', 'EXIF FocalLength', lambda x: '%s mm' % x)] + + for label, key, fmt_func in short_keys: + try: + val = fmt_func(exif_all[key]['printable']) if fmt_func \ + else exif_all[key]['printable'] + exif_short.update({label: val}) + except KeyError: + pass + + return exif_short class MediaCommentMixin(object): @@ -249,6 +288,13 @@ class MediaCommentMixin(object): """ return cleaned_markdown_conversion(self.content) + def __repr__(self): + return '<{klass} #{id} {author} "{comment}">'.format( + klass=self.__class__.__name__, + id=self.id, + author=self.get_author, + comment=self.content) + class CollectionMixin(GenerateSlugMixin): def check_slug_used(self, slug): diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 2412706e..b750375d 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -23,16 +23,18 @@ import datetime from sqlalchemy import Column, Integer, Unicode, UnicodeText, DateTime, \ Boolean, ForeignKey, UniqueConstraint, PrimaryKeyConstraint, \ - SmallInteger -from sqlalchemy.orm import relationship, backref + SmallInteger, Date +from sqlalchemy.orm import relationship, backref, with_polymorphic from sqlalchemy.orm.collections import attribute_mapped_collection from sqlalchemy.sql.expression import desc from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.util import memoized_property -from mediagoblin.db.extratypes import PathTupleWithSlashes, JSONEncoded +from mediagoblin.db.extratypes import (PathTupleWithSlashes, JSONEncoded, + MutationDict) from mediagoblin.db.base import Base, DictReadAttrProxy -from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, MediaCommentMixin, CollectionMixin, CollectionItemMixin +from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, \ + MediaCommentMixin, CollectionMixin, CollectionItemMixin from mediagoblin.tools.files import delete_media_files from mediagoblin.tools.common import import_component @@ -46,6 +48,7 @@ from migrate import changeset _log = logging.getLogger(__name__) + class User(Base, UserMixin): """ TODO: We should consider moving some rarely used fields @@ -55,21 +58,22 @@ class User(Base, UserMixin): id = Column(Integer, primary_key=True) username = Column(Unicode, nullable=False, unique=True) + # Note: no db uniqueness constraint on email because it's not + # reliable (many email systems case insensitive despite against + # the RFC) and because it would be a mess to implement at this + # point. email = Column(Unicode, nullable=False) + pw_hash = Column(Unicode) created = Column(DateTime, nullable=False, default=datetime.datetime.now) - pw_hash = Column(Unicode, nullable=False) - email_verified = Column(Boolean, default=False) - status = Column(Unicode, default=u"needs_email_verification", nullable=False) # Intented to be nullable=False, but migrations would not work for it # set to nullable=True implicitly. wants_comment_notification = Column(Boolean, default=True) + wants_notifications = Column(Boolean, default=True) license_preference = Column(Unicode) - verification_key = Column(Unicode) - is_admin = Column(Boolean, default=False, nullable=False) url = Column(Unicode) bio = Column(UnicodeText) # ?? - fp_verification_key = Column(Unicode) - fp_token_expire = Column(DateTime) + uploaded = Column(Integer, default=0) + upload_limit = Column(Integer) ## TODO # plugin data would be in a separate model @@ -78,8 +82,8 @@ class User(Base, UserMixin): return '<{0} #{1} {2} {3} "{4}">'.format( self.__class__.__name__, self.id, - 'verified' if self.email_verified else 'non-verified', - 'admin' if self.is_admin else 'user', + 'verified' if self.has_privilege(u'active') else 'non-verified', + 'admin' if self.has_privilege(u'admin') else 'user', self.username) def delete(self, **kwargs): @@ -101,6 +105,102 @@ class User(Base, UserMixin): super(User, self).delete(**kwargs) _log.info('Deleted user "{0}" account'.format(self.username)) + def has_privilege(self,*priv_names): + """ + This method checks to make sure a user has all the correct privileges + to access a piece of content. + + :param priv_names A variable number of unicode objects which rep- + -resent the different privileges which may give + the user access to this content. If you pass + multiple arguments, the user will be granted + access if they have ANY of the privileges + passed. + """ + if len(priv_names) == 1: + priv = Privilege.query.filter( + Privilege.privilege_name==priv_names[0]).one() + return (priv in self.all_privileges) + elif len(priv_names) > 1: + return self.has_privilege(priv_names[0]) or \ + self.has_privilege(*priv_names[1:]) + return False + + def is_banned(self): + """ + Checks if this user is banned. + + :returns True if self is banned + :returns False if self is not + """ + return UserBan.query.get(self.id) is not None + + +class Client(Base): + """ + Model representing a client - Used for API Auth + """ + __tablename__ = "core__clients" + + id = Column(Unicode, nullable=True, primary_key=True) + secret = Column(Unicode, nullable=False) + expirey = Column(DateTime, nullable=True) + application_type = Column(Unicode, nullable=False) + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + updated = Column(DateTime, nullable=False, default=datetime.datetime.now) + + # optional stuff + redirect_uri = Column(JSONEncoded, nullable=True) + logo_url = Column(Unicode, nullable=True) + application_name = Column(Unicode, nullable=True) + contacts = Column(JSONEncoded, nullable=True) + + def __repr__(self): + if self.application_name: + return "<Client {0} - {1}>".format(self.application_name, self.id) + else: + return "<Client {0}>".format(self.id) + +class RequestToken(Base): + """ + Model for representing the request tokens + """ + __tablename__ = "core__request_tokens" + + token = Column(Unicode, primary_key=True) + secret = Column(Unicode, nullable=False) + client = Column(Unicode, ForeignKey(Client.id)) + user = Column(Integer, ForeignKey(User.id), nullable=True) + used = Column(Boolean, default=False) + authenticated = Column(Boolean, default=False) + verifier = Column(Unicode, nullable=True) + callback = Column(Unicode, nullable=False, default=u"oob") + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + updated = Column(DateTime, nullable=False, default=datetime.datetime.now) + +class AccessToken(Base): + """ + Model for representing the access tokens + """ + __tablename__ = "core__access_tokens" + + token = Column(Unicode, nullable=False, primary_key=True) + secret = Column(Unicode, nullable=False) + user = Column(Integer, ForeignKey(User.id)) + request_token = Column(Unicode, ForeignKey(RequestToken.token)) + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + updated = Column(DateTime, nullable=False, default=datetime.datetime.now) + + +class NonceTimestamp(Base): + """ + A place the timestamp and nonce can be stored - this is for OAuth1 + """ + __tablename__ = "core__nonce_timestamps" + + nonce = Column(Unicode, nullable=False, primary_key=True) + timestamp = Column(DateTime, nullable=False, primary_key=True) + class MediaEntry(Base, MediaEntryMixin): """ @@ -119,7 +219,7 @@ class MediaEntry(Base, MediaEntryMixin): state = Column(Unicode, default=u'unprocessed', nullable=False) # or use sqlalchemy.types.Enum? license = Column(Unicode) - collected = Column(Integer, default=0) + file_size = Column(Integer, default=0) fail_error = Column(Unicode) fail_metadata = Column(JSONEncoded) @@ -194,6 +294,35 @@ class MediaEntry(Base, MediaEntryMixin): if media is not None: return media.url_for_self(urlgen) + def get_file_metadata(self, file_key, metadata_key=None): + """ + Return the file_metadata dict of a MediaFile. If metadata_key is given, + return the value of the key. + """ + media_file = MediaFile.query.filter_by(media_entry=self.id, + name=unicode(file_key)).first() + + if media_file: + if metadata_key: + return media_file.file_metadata.get(metadata_key, None) + + return media_file.file_metadata + + def set_file_metadata(self, file_key, **kwargs): + """ + Update the file_metadata of a MediaFile. + """ + media_file = MediaFile.query.filter_by(media_entry=self.id, + name=unicode(file_key)).first() + + file_metadata = media_file.file_metadata or {} + + for key, value in kwargs.iteritems(): + file_metadata[key] = value + + media_file.file_metadata = file_metadata + media_file.save() + @property def media_data(self): return getattr(self, self.media_data_ref) @@ -290,6 +419,7 @@ class MediaFile(Base): nullable=False) name_id = Column(SmallInteger, ForeignKey(FileKeynames.id), nullable=False) file_path = Column(PathTupleWithSlashes) + file_metadata = Column(MutationDict.as_mutable(JSONEncoded)) __table_args__ = ( PrimaryKeyConstraint('media_entry', 'name_id'), @@ -388,6 +518,10 @@ class MediaComment(Base, MediaCommentMixin): backref=backref("posted_comments", lazy="dynamic", cascade="all, delete-orphan")) + get_entry = relationship(MediaEntry, + backref=backref("comments", + lazy="dynamic", + cascade="all, delete-orphan")) # Cascade: Comments are somewhat owned by their MediaEntry. # So do the full thing. @@ -480,10 +614,307 @@ class ProcessingMetaData(Base): return DictReadAttrProxy(self) +class CommentSubscription(Base): + __tablename__ = 'core__comment_subscriptions' + id = Column(Integer, primary_key=True) + + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + + media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False) + media_entry = relationship(MediaEntry, + backref=backref('comment_subscriptions', + cascade='all, delete-orphan')) + + user_id = Column(Integer, ForeignKey(User.id), nullable=False) + user = relationship(User, + backref=backref('comment_subscriptions', + cascade='all, delete-orphan')) + + notify = Column(Boolean, nullable=False, default=True) + send_email = Column(Boolean, nullable=False, default=True) + + def __repr__(self): + return ('<{classname} #{id}: {user} {media} notify: ' + '{notify} email: {email}>').format( + id=self.id, + classname=self.__class__.__name__, + user=self.user, + media=self.media_entry, + notify=self.notify, + email=self.send_email) + + +class Notification(Base): + __tablename__ = 'core__notifications' + id = Column(Integer, primary_key=True) + type = Column(Unicode) + + created = Column(DateTime, nullable=False, default=datetime.datetime.now) + + user_id = Column(Integer, ForeignKey('core__users.id'), nullable=False, + index=True) + seen = Column(Boolean, default=lambda: False, index=True) + user = relationship( + User, + backref=backref('notifications', cascade='all, delete-orphan')) + + __mapper_args__ = { + 'polymorphic_identity': 'notification', + 'polymorphic_on': type + } + + def __repr__(self): + return '<{klass} #{id}: {user}: {subject} ({seen})>'.format( + id=self.id, + klass=self.__class__.__name__, + user=self.user, + subject=getattr(self, 'subject', None), + seen='unseen' if not self.seen else 'seen') + + +class CommentNotification(Notification): + __tablename__ = 'core__comment_notifications' + id = Column(Integer, ForeignKey(Notification.id), primary_key=True) + + subject_id = Column(Integer, ForeignKey(MediaComment.id)) + subject = relationship( + MediaComment, + backref=backref('comment_notifications', cascade='all, delete-orphan')) + + __mapper_args__ = { + 'polymorphic_identity': 'comment_notification' + } + + +class ProcessingNotification(Notification): + __tablename__ = 'core__processing_notifications' + + id = Column(Integer, ForeignKey(Notification.id), primary_key=True) + + subject_id = Column(Integer, ForeignKey(MediaEntry.id)) + subject = relationship( + MediaEntry, + backref=backref('processing_notifications', + cascade='all, delete-orphan')) + + __mapper_args__ = { + 'polymorphic_identity': 'processing_notification' + } + +with_polymorphic( + Notification, + [ProcessingNotification, CommentNotification]) + +class ReportBase(Base): + """ + This is the basic report object which the other reports are based off of. + + :keyword reporter_id Holds the id of the user who created + the report, as an Integer column. + :keyword report_content Hold the explanation left by the repor- + -ter to indicate why they filed the + report in the first place, as a + Unicode column. + :keyword reported_user_id Holds the id of the user who created + the content which was reported, as + an Integer column. + :keyword created Holds a datetime column of when the re- + -port was filed. + :keyword discriminator This column distinguishes between the + different types of reports. + :keyword resolver_id Holds the id of the moderator/admin who + resolved the report. + :keyword resolved Holds the DateTime object which descri- + -bes when this report was resolved + :keyword result Holds the UnicodeText column of the + resolver's reasons for resolving + the report this way. Some of this + is auto-generated + """ + __tablename__ = 'core__reports' + id = Column(Integer, primary_key=True) + reporter_id = Column(Integer, ForeignKey(User.id), nullable=False) + reporter = relationship( + User, + backref=backref("reports_filed_by", + lazy="dynamic", + cascade="all, delete-orphan"), + primaryjoin="User.id==ReportBase.reporter_id") + report_content = Column(UnicodeText) + reported_user_id = Column(Integer, ForeignKey(User.id), nullable=False) + reported_user = relationship( + User, + backref=backref("reports_filed_on", + lazy="dynamic", + cascade="all, delete-orphan"), + primaryjoin="User.id==ReportBase.reported_user_id") + created = Column(DateTime, nullable=False, default=datetime.datetime.now()) + discriminator = Column('type', Unicode(50)) + resolver_id = Column(Integer, ForeignKey(User.id)) + resolver = relationship( + User, + backref=backref("reports_resolved_by", + lazy="dynamic", + cascade="all, delete-orphan"), + primaryjoin="User.id==ReportBase.resolver_id") + + resolved = Column(DateTime) + result = Column(UnicodeText) + __mapper_args__ = {'polymorphic_on': discriminator} + + def is_comment_report(self): + return self.discriminator=='comment_report' + + def is_media_entry_report(self): + return self.discriminator=='media_report' + + def is_archived_report(self): + return self.resolved is not None + + def archive(self,resolver_id, resolved, result): + self.resolver_id = resolver_id + self.resolved = resolved + self.result = result + + +class CommentReport(ReportBase): + """ + Reports that have been filed on comments. + :keyword comment_id Holds the integer value of the reported + comment's ID + """ + __tablename__ = 'core__reports_on_comments' + __mapper_args__ = {'polymorphic_identity': 'comment_report'} + + id = Column('id',Integer, ForeignKey('core__reports.id'), + primary_key=True) + comment_id = Column(Integer, ForeignKey(MediaComment.id), nullable=True) + comment = relationship( + MediaComment, backref=backref("reports_filed_on", + lazy="dynamic")) + + +class MediaReport(ReportBase): + """ + Reports that have been filed on media entries + :keyword media_entry_id Holds the integer value of the reported + media entry's ID + """ + __tablename__ = 'core__reports_on_media' + __mapper_args__ = {'polymorphic_identity': 'media_report'} + + id = Column('id',Integer, ForeignKey('core__reports.id'), + primary_key=True) + media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=True) + media_entry = relationship( + MediaEntry, + backref=backref("reports_filed_on", + lazy="dynamic")) + +class UserBan(Base): + """ + Holds the information on a specific user's ban-state. As long as one of + these is attached to a user, they are banned from accessing mediagoblin. + When they try to log in, they are greeted with a page that tells them + the reason why they are banned and when (if ever) the ban will be + lifted + + :keyword user_id Holds the id of the user this object is + attached to. This is a one-to-one + relationship. + :keyword expiration_date Holds the date that the ban will be lifted. + If this is null, the ban is permanent + unless a moderator manually lifts it. + :keyword reason Holds the reason why the user was banned. + """ + __tablename__ = 'core__user_bans' + + user_id = Column(Integer, ForeignKey(User.id), nullable=False, + primary_key=True) + expiration_date = Column(Date) + reason = Column(UnicodeText, nullable=False) + + +class Privilege(Base): + """ + The Privilege table holds all of the different privileges a user can hold. + If a user 'has' a privilege, the User object is in a relationship with the + privilege object. + + :keyword privilege_name Holds a unicode object that is the recognizable + name of this privilege. This is the column + used for identifying whether or not a user + has a necessary privilege or not. + + """ + __tablename__ = 'core__privileges' + + id = Column(Integer, nullable=False, primary_key=True) + privilege_name = Column(Unicode, nullable=False, unique=True) + all_users = relationship( + User, + backref='all_privileges', + secondary="core__privileges_users") + + def __init__(self, privilege_name): + ''' + Currently consructors are required for tables that are initialized thru + the FOUNDATIONS system. This is because they need to be able to be con- + -structed by a list object holding their arg*s + ''' + self.privilege_name = privilege_name + + def __repr__(self): + return "<Privilege %s>" % (self.privilege_name) + + +class PrivilegeUserAssociation(Base): + ''' + This table holds the many-to-many relationship between User and Privilege + ''' + + __tablename__ = 'core__privileges_users' + + privilege_id = Column( + 'core__privilege_id', + Integer, + ForeignKey(User.id), + primary_key=True) + user_id = Column( + 'core__user_id', + Integer, + ForeignKey(Privilege.id), + primary_key=True) + MODELS = [ - User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem, MediaFile, FileKeynames, - MediaAttachmentFile, ProcessingMetaData] + User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem, + MediaFile, FileKeynames, MediaAttachmentFile, ProcessingMetaData, + Notification, CommentNotification, ProcessingNotification, Client, + CommentSubscription, ReportBase, CommentReport, MediaReport, UserBan, + Privilege, PrivilegeUserAssociation, + RequestToken, AccessToken, NonceTimestamp] +""" + Foundations are the default rows that are created immediately after the tables + are initialized. Each entry to this dictionary should be in the format of: + ModelConstructorObject:List of Dictionaries + (Each Dictionary represents a row on the Table to be created, containing each + of the columns' names as a key string, and each of the columns' values as a + value) + + ex. [NOTE THIS IS NOT BASED OFF OF OUR USER TABLE] + user_foundations = [{'name':u'Joanna', 'age':24}, + {'name':u'Andrea', 'age':41}] + + FOUNDATIONS = {User:user_foundations} +""" +privilege_foundations = [{'privilege_name':u'admin'}, + {'privilege_name':u'moderator'}, + {'privilege_name':u'uploader'}, + {'privilege_name':u'reporter'}, + {'privilege_name':u'commenter'}, + {'privilege_name':u'active'}] +FOUNDATIONS = {Privilege:privilege_foundations} ###################################################### # Special, migrations-tracking table diff --git a/mediagoblin/db/models_v0.py b/mediagoblin/db/models_v0.py index ec51a1f5..bdedec2e 100644 --- a/mediagoblin/db/models_v0.py +++ b/mediagoblin/db/models_v0.py @@ -18,6 +18,29 @@ TODO: indexes on foreignkeys, where useful. """ +########################################################################### +# WHAT IS THIS FILE? +# ------------------ +# +# Upon occasion, someone runs into this file and wonders why we have +# both a models.py and a models_v0.py. +# +# The short of it is: you can ignore this file. +# +# The long version is, in two parts: +# +# - We used to use MongoDB, then we switched to SQL and SQLAlchemy. +# We needed to convert peoples' databases; the script we had would +# switch them to the first version right after Mongo, convert over +# all their tables, then run any migrations that were added after. +# +# - That script is now removed, but there is some discussion of +# writing a test that would set us at the first SQL migration and +# run everything after. If we wrote that, this file would still be +# useful. But for now, it's legacy! +# +########################################################################### + import datetime import sys diff --git a/mediagoblin/db/open.py b/mediagoblin/db/open.py index 0b1679fb..4ff0945f 100644 --- a/mediagoblin/db/open.py +++ b/mediagoblin/db/open.py @@ -52,10 +52,6 @@ class DatabaseMaster(object): def load_models(app_config): import mediagoblin.db.models - for media_type in app_config['media_types']: - _log.debug("Loading %s.models", media_type) - __import__(media_type + ".models") - for plugin in mg_globals.global_config.get('plugins', {}).keys(): _log.debug("Loading %s.models", plugin) try: diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py index 6ffec44d..7a0a3a73 100644 --- a/mediagoblin/db/util.py +++ b/mediagoblin/db/util.py @@ -24,7 +24,7 @@ from mediagoblin.db.models import MediaEntry, Tag, MediaTag, Collection def atomic_update(table, query_dict, update_values): - table.find(query_dict).update(update_values, + table.query.filter_by(**query_dict).update(update_values, synchronize_session=False) Session.commit() @@ -67,7 +67,6 @@ def check_collection_slug_used(creator_id, slug, ignore_c_id): does_exist = Session.query(Collection.id).filter(filt).first() is not None return does_exist - if __name__ == '__main__': from mediagoblin.db.open import setup_connection_and_db_from_config diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py index f3535fcf..8515d091 100644 --- a/mediagoblin/decorators.py +++ b/mediagoblin/decorators.py @@ -18,25 +18,49 @@ from functools import wraps from urlparse import urljoin from werkzeug.exceptions import Forbidden, NotFound -from werkzeug.urls import url_quote +from oauthlib.oauth1 import ResourceEndpoint from mediagoblin import mg_globals as mgg -from mediagoblin.db.models import MediaEntry, User -from mediagoblin.tools.response import redirect, render_404 +from mediagoblin import messages +from mediagoblin.db.models import MediaEntry, User, MediaComment +from mediagoblin.tools.response import ( + redirect, render_404, + render_user_banned, json_response) +from mediagoblin.tools.translate import pass_to_ugettext as _ + +from mediagoblin.oauth.tools.request import decode_authorization_header +from mediagoblin.oauth.oauth import GMGRequestValidator + + +def user_not_banned(controller): + """ + Requires that the user has not been banned. Otherwise redirects to the page + explaining why they have been banned + """ + @wraps(controller) + def wrapper(request, *args, **kwargs): + if request.user: + if request.user.is_banned(): + return render_user_banned(request) + return controller(request, *args, **kwargs) + + return wrapper def require_active_login(controller): """ - Require an active login from the user. + Require an active login from the user. If the user is banned, redirects to + the "You are Banned" page. """ @wraps(controller) + @user_not_banned def new_controller_func(request, *args, **kwargs): if request.user and \ - request.user.status == u'needs_email_verification': + not request.user.has_privilege(u'active'): return redirect( request, 'mediagoblin.user_pages.user_home', user=request.user.username) - elif not request.user or request.user.status != u'active': + elif not request.user or not request.user.has_privilege(u'active'): next_url = urljoin( request.urlgen('mediagoblin.auth.login', qualified=True), @@ -49,6 +73,34 @@ def require_active_login(controller): return new_controller_func + +def user_has_privilege(privilege_name): + """ + Requires that a user have a particular privilege in order to access a page. + In order to require that a user have multiple privileges, use this + decorator twice on the same view. This decorator also makes sure that the + user is not banned, or else it redirects them to the "You are Banned" page. + + :param privilege_name A unicode object that is that represents + the privilege object. This object is + the name of the privilege, as assigned + in the Privilege.privilege_name column + """ + + def user_has_privilege_decorator(controller): + @wraps(controller) + @require_active_login + def wrapper(request, *args, **kwargs): + user_id = request.user.id + if not request.user.has_privilege(privilege_name): + raise Forbidden() + + return controller(request, *args, **kwargs) + + return wrapper + return user_has_privilege_decorator + + def active_user_from_url(controller): """Retrieve User() from <user> URL pattern and pass in as url_user=... @@ -71,7 +123,7 @@ def user_may_delete_media(controller): @wraps(controller) def wrapper(request, *args, **kwargs): uploader_id = kwargs['media'].uploader - if not (request.user.is_admin or + if not (request.user.has_privilege(u'admin') or request.user.id == uploader_id): raise Forbidden() @@ -86,9 +138,9 @@ def user_may_alter_collection(controller): """ @wraps(controller) def wrapper(request, *args, **kwargs): - creator_id = request.db.User.find_one( - {'username': request.matchdict['user']}).id - if not (request.user.is_admin or + creator_id = request.db.User.query.filter_by( + username=request.matchdict['user']).first().id + if not (request.user.has_privilege(u'admin') or request.user.id == creator_id): raise Forbidden() @@ -161,15 +213,15 @@ def get_user_collection(controller): """ @wraps(controller) def wrapper(request, *args, **kwargs): - user = request.db.User.find_one( - {'username': request.matchdict['user']}) + user = request.db.User.query.filter_by( + username=request.matchdict['user']).first() if not user: return render_404(request) - collection = request.db.Collection.find_one( - {'slug': request.matchdict['collection'], - 'creator': user.id}) + collection = request.db.Collection.query.filter_by( + slug=request.matchdict['collection'], + creator=user.id).first() # Still no collection? Okay, 404. if not collection: @@ -186,14 +238,14 @@ def get_user_collection_item(controller): """ @wraps(controller) def wrapper(request, *args, **kwargs): - user = request.db.User.find_one( - {'username': request.matchdict['user']}) + user = request.db.User.query.filter_by( + username=request.matchdict['user']).first() if not user: return render_404(request) - collection_item = request.db.CollectionItem.find_one( - {'id': request.matchdict['collection_item'] }) + collection_item = request.db.CollectionItem.query.filter_by( + id=request.matchdict['collection_item']).first() # Still no collection item? Okay, 404. if not collection_item: @@ -235,3 +287,131 @@ def get_workbench(func): return func(*args, workbench=workbench, **kwargs) return new_func + + +def allow_registration(controller): + """ Decorator for if registration is enabled""" + @wraps(controller) + def wrapper(request, *args, **kwargs): + if not mgg.app_config["allow_registration"]: + messages.add_message( + request, + messages.WARNING, + _('Sorry, registration is disabled on this instance.')) + return redirect(request, "index") + + return controller(request, *args, **kwargs) + + return wrapper + +def allow_reporting(controller): + """ Decorator for if reporting is enabled""" + @wraps(controller) + def wrapper(request, *args, **kwargs): + if not mgg.app_config["allow_reporting"]: + messages.add_message( + request, + messages.WARNING, + _('Sorry, reporting is disabled on this instance.')) + return redirect(request, 'index') + + return controller(request, *args, **kwargs) + + return wrapper + +def get_optional_media_comment_by_id(controller): + """ + Pass in a MediaComment based off of a url component. Because of this decor- + -ator's use in filing Media or Comment Reports, it has two valid outcomes. + + :returns The view function being wrapped with kwarg `comment` set to + the MediaComment who's id is in the URL. If there is a + comment id in the URL and if it is valid. + :returns The view function being wrapped with kwarg `comment` set to + None. If there is no comment id in the URL. + :returns A 404 Error page, if there is a comment if in the URL and it + is invalid. + """ + @wraps(controller) + def wrapper(request, *args, **kwargs): + if 'comment' in request.matchdict: + comment = MediaComment.query.filter_by( + id=request.matchdict['comment']).first() + + if comment is None: + return render_404(request) + + return controller(request, comment=comment, *args, **kwargs) + else: + return controller(request, comment=None, *args, **kwargs) + return wrapper + + +def auth_enabled(controller): + """Decorator for if an auth plugin is enabled""" + @wraps(controller) + def wrapper(request, *args, **kwargs): + if not mgg.app.auth: + messages.add_message( + request, + messages.WARNING, + _('Sorry, authentication is disabled on this instance.')) + return redirect(request, 'index') + + return controller(request, *args, **kwargs) + + return wrapper + +def require_admin_or_moderator_login(controller): + """ + Require a login from an administrator or a moderator. + """ + @wraps(controller) + def new_controller_func(request, *args, **kwargs): + if request.user and \ + not request.user.has_privilege(u'admin',u'moderator'): + + raise Forbidden() + elif not request.user: + next_url = urljoin( + request.urlgen('mediagoblin.auth.login', + qualified=True), + request.url) + + return redirect(request, 'mediagoblin.auth.login', + next=next_url) + + return controller(request, *args, **kwargs) + + return new_controller_func + + + +def oauth_required(controller): + """ Used to wrap API endpoints where oauth is required """ + @wraps(controller) + def wrapper(request, *args, **kwargs): + data = request.headers + authorization = decode_authorization_header(data) + + if authorization == dict(): + error = "Missing required parameter." + return json_response({"error": error}, status=400) + + + request_validator = GMGRequestValidator() + resource_endpoint = ResourceEndpoint(request_validator) + valid, request = resource_endpoint.validate_protected_resource_request( + uri=request.url, + http_method=request.method, + body=request.get_data(), + headers=dict(request.headers), + ) + + if not valid: + error = "Invalid oauth prarameter." + return json_response({"error": error}, status=400) + + return controller(request, *args, **kwargs) + + return wrapper diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py index ef270237..2c9b5e99 100644 --- a/mediagoblin/edit/forms.py +++ b/mediagoblin/edit/forms.py @@ -16,9 +16,11 @@ import wtforms -from mediagoblin.tools.text import tag_length_validator, TOO_LONG_TAG_WARNING +from mediagoblin.tools.text import tag_length_validator from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.tools.licenses import licenses_as_choices +from mediagoblin.auth.tools import normalize_user_or_email_field + class EditForm(wtforms.Form): title = wtforms.TextField( @@ -59,17 +61,10 @@ class EditProfileForm(wtforms.Form): class EditAccountForm(wtforms.Form): - old_password = wtforms.PasswordField( - _('Old password'), - description=_( - "Enter your old password to prove you own this account.")) - new_password = wtforms.PasswordField( - _('New password'), - [ - wtforms.validators.Optional(), - wtforms.validators.Length(min=6, max=30) - ], - id="password") + wants_comment_notification = wtforms.BooleanField( + description=_("Email me when others comment on my media")) + wants_notifications = wtforms.BooleanField( + description=_("Enable insite notifications about events.")) license_preference = wtforms.SelectField( _('License preference'), [ @@ -78,8 +73,6 @@ class EditAccountForm(wtforms.Form): ], choices=licenses_as_choices(), description=_('This will be your default license on upload forms.')) - wants_comment_notification = wtforms.BooleanField( - label=_("Email me when others comment on my media")) class EditAttachmentsForm(wtforms.Form): @@ -88,6 +81,7 @@ class EditAttachmentsForm(wtforms.Form): attachment_file = wtforms.FileField( 'File') + class EditCollectionForm(wtforms.Form): title = wtforms.TextField( _('Title'), @@ -103,3 +97,28 @@ class EditCollectionForm(wtforms.Form): description=_( "The title part of this collection's address. " "You usually don't need to change this.")) + + +class ChangePassForm(wtforms.Form): + old_password = wtforms.PasswordField( + _('Old password'), + [wtforms.validators.Required()], + description=_( + "Enter your old password to prove you own this account.")) + new_password = wtforms.PasswordField( + _('New password'), + [wtforms.validators.Required(), + wtforms.validators.Length(min=6, max=30)], + id="password") + + +class ChangeEmailForm(wtforms.Form): + new_email = wtforms.TextField( + _('New email address'), + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_user=False)]) + password = wtforms.PasswordField( + _('Password'), + [wtforms.validators.Required()], + description=_( + "Enter your password to prove you own this account.")) diff --git a/mediagoblin/edit/lib.py b/mediagoblin/edit/lib.py index aab537a0..6acebc96 100644 --- a/mediagoblin/edit/lib.py +++ b/mediagoblin/edit/lib.py @@ -19,6 +19,6 @@ def may_edit_media(request, media): """Check, if the request's user may edit the media details""" if media.uploader == request.user.id: return True - if request.user.is_admin: + if request.user.has_privilege(u'admin'): return True return False diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py index 035a766f..a2d03d26 100644 --- a/mediagoblin/edit/routing.py +++ b/mediagoblin/edit/routing.py @@ -24,3 +24,7 @@ add_route('mediagoblin.edit.account', '/edit/account/', 'mediagoblin.edit.views:edit_account') add_route('mediagoblin.edit.delete_account', '/edit/account/delete/', 'mediagoblin.edit.views:delete_account') +add_route('mediagoblin.edit.verify_email', '/edit/verify_email/', + 'mediagoblin.edit.views:verify_email') +add_route('mediagoblin.edit.email', '/edit/email/', + 'mediagoblin.edit.views:change_email') diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 34b7aaca..80590875 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -16,24 +16,31 @@ from datetime import datetime +from itsdangerous import BadSignature from werkzeug.exceptions import Forbidden from werkzeug.utils import secure_filename from mediagoblin import messages from mediagoblin import mg_globals -from mediagoblin.auth import lib as auth_lib +from mediagoblin.auth import (check_password, + tools as auth_tools) from mediagoblin.edit import forms from mediagoblin.edit.lib import may_edit_media from mediagoblin.decorators import (require_active_login, active_user_from_url, - get_media_entry_by_id, - user_may_alter_collection, get_user_collection) -from mediagoblin.tools.response import render_to_response, redirect + get_media_entry_by_id, user_may_alter_collection, + get_user_collection) +from mediagoblin.tools.crypto import get_timed_signer_url +from mediagoblin.tools.mail import email_debug_message +from mediagoblin.tools.response import (render_to_response, + redirect, redirect_obj, render_404) from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.template import render_template from mediagoblin.tools.text import ( convert_to_tag_list_of_dicts, media_tags_as_string) from mediagoblin.tools.url import slugify from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used +from mediagoblin.db.models import User import mimetypes @@ -74,10 +81,9 @@ def edit_media(request, media): media.slug = slug media.save() - return redirect(request, - location=media.url_for_self(request.urlgen)) + return redirect_obj(request, media) - if request.user.is_admin \ + if request.user.has_privilege(u'admin') \ and media.uploader != request.user.id \ and request.method != 'POST': messages.add_message( @@ -178,7 +184,7 @@ def legacy_edit_profile(request): def edit_profile(request, url_user=None): # admins may edit any user profile if request.user.username != url_user.username: - if not request.user.is_admin: + if not request.user.has_privilege(u'admin'): raise Forbidden(_("You can only edit your own profile.")) # No need to warn again if admin just submitted an edited profile @@ -212,47 +218,32 @@ def edit_profile(request, url_user=None): {'user': user, 'form': form}) +EMAIL_VERIFICATION_TEMPLATE = ( + u'{uri}?' + u'token={verification_key}') + @require_active_login def edit_account(request): user = request.user form = forms.EditAccountForm(request.form, wants_comment_notification=user.wants_comment_notification, - license_preference=user.license_preference) + license_preference=user.license_preference, + wants_notifications=user.wants_notifications) - if request.method == 'POST': - form_validated = form.validate() - - if form_validated and \ - form.wants_comment_notification.validate(form): - user.wants_comment_notification = \ - form.wants_comment_notification.data - - if form_validated and \ - form.new_password.data or form.old_password.data: - password_matches = auth_lib.bcrypt_check_password( - form.old_password.data, - user.pw_hash) - if password_matches: - #the entire form validates and the password matches - user.pw_hash = auth_lib.bcrypt_gen_password_hash( - form.new_password.data) - else: - form.old_password.errors.append(_('Wrong password')) - - if form_validated and \ - form.license_preference.validate(form): - user.license_preference = \ - form.license_preference.data - - if form_validated and not form.errors: - user.save() - messages.add_message(request, - messages.SUCCESS, - _("Account settings saved")) - return redirect(request, - 'mediagoblin.user_pages.user_home', - user=user.username) + if request.method == 'POST' and form.validate(): + user.wants_comment_notification = form.wants_comment_notification.data + user.wants_notifications = form.wants_notifications.data + + user.license_preference = form.license_preference.data + + user.save() + messages.add_message(request, + messages.SUCCESS, + _("Account settings saved")) + return redirect(request, + 'mediagoblin.user_pages.user_home', + user=user.username) return render_to_response( request, @@ -312,9 +303,9 @@ def edit_collection(request, collection): form.slug.data, collection.id) # Make sure there isn't already a Collection with this title - existing_collection = request.db.Collection.find_one({ - 'creator': request.user.id, - 'title':form.title.data}) + existing_collection = request.db.Collection.query.filter_by( + creator=request.user.id, + title=form.title.data).first() if existing_collection and existing_collection.id != collection.id: messages.add_message( @@ -331,11 +322,9 @@ def edit_collection(request, collection): collection.save() - return redirect(request, "mediagoblin.user_pages.user_collection", - user=collection.get_creator.username, - collection=collection.slug) + return redirect_obj(request, collection) - if request.user.is_admin \ + if request.user.has_privilege(u'admin') \ and collection.creator != request.user.id \ and request.method != 'POST': messages.add_message( @@ -347,3 +336,99 @@ def edit_collection(request, collection): 'mediagoblin/edit/edit_collection.html', {'collection': collection, 'form': form}) + + +def verify_email(request): + """ + Email verification view for changing email address + """ + # If no token, we can't do anything + if not 'token' in request.GET: + return render_404(request) + + # Catch error if token is faked or expired + token = None + try: + token = get_timed_signer_url("mail_verification_token") \ + .loads(request.GET['token'], max_age=10*24*3600) + except BadSignature: + messages.add_message( + request, + messages.ERROR, + _('The verification key or user id is incorrect.')) + + return redirect( + request, + 'index') + + user = User.query.filter_by(id=int(token['user'])).first() + + if user: + user.email = token['email'] + user.save() + + messages.add_message( + request, + messages.SUCCESS, + _('Your email address has been verified.')) + + else: + messages.add_message( + request, + messages.ERROR, + _('The verification key or user id is incorrect.')) + + return redirect( + request, 'mediagoblin.user_pages.user_home', + user=user.username) + + +def change_email(request): + """ View to change the user's email """ + form = forms.ChangeEmailForm(request.form) + user = request.user + + # If no password authentication, no need to enter a password + if 'pass_auth' not in request.template_env.globals or not user.pw_hash: + form.__delitem__('password') + + if request.method == 'POST' and form.validate(): + new_email = form.new_email.data + users_with_email = User.query.filter_by( + email=new_email).count() + + if users_with_email: + form.new_email.errors.append( + _('Sorry, a user with that email address' + ' already exists.')) + + if form.password and user.pw_hash and not check_password( + form.password.data, user.pw_hash): + form.password.errors.append( + _('Wrong password')) + + if not form.errors: + verification_key = get_timed_signer_url( + 'mail_verification_token').dumps({ + 'user': user.id, + 'email': new_email}) + + rendered_email = render_template( + request, 'mediagoblin/edit/verification.txt', + {'username': user.username, + 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format( + uri=request.urlgen('mediagoblin.edit.verify_email', + qualified=True), + verification_key=verification_key)}) + + email_debug_message(request) + auth_tools.send_verification_email(user, request, new_email, + rendered_email) + + return redirect(request, 'mediagoblin.edit.account') + + return render_to_response( + request, + 'mediagoblin/edit/change_email.html', + {'form': form, + 'user': user}) diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py index 6aed4f6c..a1eb599d 100644 --- a/mediagoblin/gmg_commands/__init__.py +++ b/mediagoblin/gmg_commands/__init__.py @@ -41,11 +41,23 @@ SUBCOMMAND_MAP = { 'setup': 'mediagoblin.gmg_commands.dbupdate:dbupdate_parse_setup', 'func': 'mediagoblin.gmg_commands.dbupdate:dbupdate', 'help': 'Set up or update the SQL database'}, - 'theme': { - 'setup': 'mediagoblin.gmg_commands.theme:theme_parser_setup', - 'func': 'mediagoblin.gmg_commands.theme:theme', - 'help': 'Theming commands', - } + 'assetlink': { + 'setup': 'mediagoblin.gmg_commands.assetlink:assetlink_parser_setup', + 'func': 'mediagoblin.gmg_commands.assetlink:assetlink', + 'help': 'Link assets for themes and plugins for static serving'}, + 'reprocess': { + 'setup': 'mediagoblin.gmg_commands.reprocess:reprocess_parser_setup', + 'func': 'mediagoblin.gmg_commands.reprocess:reprocess', + 'help': 'Reprocess media entries'}, + 'addmedia': { + 'setup': 'mediagoblin.gmg_commands.addmedia:parser_setup', + 'func': 'mediagoblin.gmg_commands.addmedia:addmedia', + 'help': 'Reprocess media entries'}, + # 'theme': { + # 'setup': 'mediagoblin.gmg_commands.theme:theme_parser_setup', + # 'func': 'mediagoblin.gmg_commands.theme:theme', + # 'help': 'Theming commands', + # } ## These might be useful, mayyyybe, but don't really work anymore ## due to mongo change and the "versatility" of sql options. diff --git a/mediagoblin/gmg_commands/addmedia.py b/mediagoblin/gmg_commands/addmedia.py new file mode 100644 index 00000000..c33a8c56 --- /dev/null +++ b/mediagoblin/gmg_commands/addmedia.py @@ -0,0 +1,105 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from mediagoblin.gmg_commands import util as commands_util +from mediagoblin.submit.lib import ( + submit_media, get_upload_file_limits, + FileUploadLimit, UserUploadLimit, UserPastUploadLimit) + +from mediagoblin import mg_globals + + +def parser_setup(subparser): + subparser.add_argument( + 'username', + help="Name of user this media entry belongs to") + subparser.add_argument( + 'filename', + help="Local file on filesystem") + subparser.add_argument( + "-d", "--description", + help="Description for this media entry") + subparser.add_argument( + "-t", "--title", + help="Title for this media entry") + subparser.add_argument( + "-l", "--license", + help=( + "License this media entry will be released under. " + "Should be a URL.")) + subparser.add_argument( + "-T", "--tags", + help=( + "Comma separated list of tags for this media entry.")) + subparser.add_argument( + "-s", "--slug", + help=( + "Slug for this media entry. " + "Will be autogenerated if unspecified.")) + + subparser.add_argument( + '--celery', + action='store_true', + help="Don't process eagerly, pass off to celery") + + +def addmedia(args): + # Run eagerly unless explicetly set not to + if not args.celery: + os.environ['CELERY_ALWAYS_EAGER'] = 'true' + + app = commands_util.setup_app(args) + + # get the user + user = app.db.User.query.filter_by(username=args.username.lower()).first() + if user is None: + print "Sorry, no user by username '%s'" % args.username + return + + # check for the file, if it exists... + filename = os.path.split(args.filename)[-1] + abs_filename = os.path.abspath(args.filename) + if not os.path.exists(abs_filename): + print "Can't find a file with filename '%s'" % args.filename + return + + upload_limit, max_file_size = get_upload_file_limits(user) + + def maybe_unicodeify(some_string): + # this is kinda terrible + if some_string is None: + return None + else: + return unicode(some_string) + + try: + submit_media( + mg_app=app, + user=user, + submitted_file=file(abs_filename, 'r'), filename=filename, + title=maybe_unicodeify(args.title), + description=maybe_unicodeify(args.description), + license=maybe_unicodeify(args.license), + tags_string=maybe_unicodeify(args.tags) or u"", + upload_limit=upload_limit, max_file_size=max_file_size) + except FileUploadLimit: + print "This file is larger than the upload limits for this site." + except UserUploadLimit: + print "This file will put this user past their upload limits." + except UserPastUploadLimit: + print "This user is already past their upload limits." diff --git a/mediagoblin/gmg_commands/assetlink.py b/mediagoblin/gmg_commands/assetlink.py new file mode 100644 index 00000000..148ebe9e --- /dev/null +++ b/mediagoblin/gmg_commands/assetlink.py @@ -0,0 +1,151 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from mediagoblin import mg_globals +from mediagoblin.init import setup_global_and_app_config +from mediagoblin.gmg_commands import util as commands_util +from mediagoblin.tools.theme import register_themes +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.common import simple_printer +from mediagoblin.tools import pluginapi + + +def assetlink_parser_setup(subparser): + # theme_subparsers = subparser.add_subparsers( + # dest=u"subcommand", + # help=u'Assetlink options') + + # # Install command + # install_parser = theme_subparsers.add_parser( + # u'install', help=u'Install a theme to this mediagoblin instance') + # install_parser.add_argument( + # u'themefile', help=u'The theme archive to be installed') + + # theme_subparsers.add_parser( + # u'assetlink', + # help=( + # u"Link the currently installed theme's assets " + # u"to the served theme asset directory")) + pass + + +########### +# Utilities +########### + +def link_theme_assets(theme, link_dir, printer=simple_printer): + """ + Returns a list of string of text telling the user what we did + which should be printable. + """ + link_dir = link_dir.rstrip(os.path.sep) + link_parent_dir = os.path.dirname(link_dir) + + if theme is None: + printer(_("Cannot link theme... no theme set\n")) + return + + def _maybe_unlink_link_dir(): + """unlink link directory if it exists""" + if os.path.lexists(link_dir) \ + and os.path.islink(link_dir): + os.unlink(link_dir) + return True + + return + + if theme.get('assets_dir') is None: + printer(_("No asset directory for this theme\n")) + if _maybe_unlink_link_dir(): + printer( + _("However, old link directory symlink found; removed.\n")) + return + + _maybe_unlink_link_dir() + + # make the link directory parent dirs if necessary + if not os.path.lexists(link_parent_dir): + os.makedirs(link_parent_dir) + + os.symlink( + theme['assets_dir'].rstrip(os.path.sep), + link_dir) + printer("Linked the theme's asset directory:\n %s\nto:\n %s\n" % ( + theme['assets_dir'], link_dir)) + + +def link_plugin_assets(plugin_static, plugins_link_dir, printer=simple_printer): + """ + Arguments: + - plugin_static: a mediagoblin.tools.staticdirect.PluginStatic instance + representing the static assets of this plugins' configuration + - plugins_link_dir: Base directory plugins are linked from + """ + # link_dir is the final directory we'll link to, a combination of + # the plugin assetlink directory and plugin_static.name + link_dir = os.path.join( + plugins_link_dir.rstrip(os.path.sep), plugin_static.name) + + # make the link directory parent dirs if necessary + if not os.path.lexists(plugins_link_dir): + os.makedirs(plugins_link_dir) + + # See if the link_dir already exists. + if os.path.lexists(link_dir): + # if this isn't a symlink, there's something wrong... error out. + if not os.path.islink(link_dir): + printer(_('Could not link "%s": %s exists and is not a symlink\n') % ( + plugin_static.name, link_dir)) + return + + # if this is a symlink and the path already exists, skip it. + if os.path.realpath(link_dir) == plugin_static.file_path: + # Is this comment helpful or not? + printer(_('Skipping "%s"; already set up.\n') % ( + plugin_static.name)) + return + + # Otherwise, it's a link that went to something else... unlink it + printer(_('Old link found for "%s"; removing.\n') % ( + plugin_static.name)) + os.unlink(link_dir) + + os.symlink( + plugin_static.file_path.rstrip(os.path.sep), + link_dir) + printer('Linked asset directory for plugin "%s":\n %s\nto:\n %s\n' % ( + plugin_static.name, + plugin_static.file_path.rstrip(os.path.sep), + link_dir)) + + +def assetlink(args): + """ + Link the asset directory of the currently installed theme and plugins + """ + mgoblin_app = commands_util.setup_app(args) + app_config = mg_globals.app_config + + # link theme + link_theme_assets(mgoblin_app.current_theme, app_config['theme_linked_assets_dir']) + + # link plugin assets + ## ... probably for this we need the whole application initialized + for plugin_static in pluginapi.hook_runall("static_setup"): + link_plugin_assets( + plugin_static, app_config['plugin_linked_assets_dir']) diff --git a/mediagoblin/gmg_commands/dbupdate.py b/mediagoblin/gmg_commands/dbupdate.py index 32700c40..05762946 100644 --- a/mediagoblin/gmg_commands/dbupdate.py +++ b/mediagoblin/gmg_commands/dbupdate.py @@ -25,24 +25,26 @@ from mediagoblin.tools.common import import_component _log = logging.getLogger(__name__) logging.basicConfig() -_log.setLevel(logging.DEBUG) +## Let's not set the level as debug by default to avoid confusing users :) +# _log.setLevel(logging.DEBUG) def dbupdate_parse_setup(subparser): pass class DatabaseData(object): - def __init__(self, name, models, migrations): + def __init__(self, name, models, foundations, migrations): self.name = name self.models = models + self.foundations = foundations self.migrations = migrations def make_migration_manager(self, session): return MigrationManager( - self.name, self.models, self.migrations, session) + self.name, self.models, self.foundations, self.migrations, session) -def gather_database_data(media_types, plugins): +def gather_database_data(plugins): """ Gather all database data relevant to the extensions we have installed so we can do migrations and table initialization. @@ -54,17 +56,11 @@ def gather_database_data(media_types, plugins): # Add main first from mediagoblin.db.models import MODELS as MAIN_MODELS from mediagoblin.db.migrations import MIGRATIONS as MAIN_MIGRATIONS + from mediagoblin.db.models import FOUNDATIONS as MAIN_FOUNDATIONS managed_dbdata.append( DatabaseData( - u'__main__', MAIN_MODELS, MAIN_MIGRATIONS)) - - # Then get all registered media managers (eventually, plugins) - for media_type in media_types: - models = import_component('%s.models:MODELS' % media_type) - migrations = import_component('%s.migrations:MIGRATIONS' % media_type) - managed_dbdata.append( - DatabaseData(media_type, models, migrations)) + u'__main__', MAIN_MODELS, MAIN_FOUNDATIONS, MAIN_MIGRATIONS)) for plugin in plugins: try: @@ -78,6 +74,7 @@ def gather_database_data(media_types, plugins): except AttributeError as exc: _log.warning('Could not find MODELS in {0}.models, have you \ forgotten to add it? ({1})'.format(plugin, exc)) + models = [] try: migrations = import_component('{0}.migrations:MIGRATIONS'.format( @@ -89,12 +86,20 @@ forgotten to add it? ({1})'.format(plugin, exc)) migrations = {} except AttributeError as exc: - _log.debug('Cloud not find MIGRATIONS in {0}.migrations, have you \ + _log.debug('Could not find MIGRATIONS in {0}.migrations, have you \ forgotten to add it? ({1})'.format(plugin, exc)) + migrations = {} + + try: + foundations = import_component('{0}.models:FOUNDATIONS'.format(plugin)) + except ImportError as exc: + foundations = {} + except AttributeError as exc: + foundations = {} if models: managed_dbdata.append( - DatabaseData(plugin, models, migrations)) + DatabaseData(plugin, models, foundations, migrations)) return managed_dbdata @@ -108,14 +113,25 @@ def run_dbupdate(app_config, global_config): in the future, plugins) """ + # Set up the database + db = setup_connection_and_db_from_config(app_config, migrations=True) + #Run the migrations + run_all_migrations(db, app_config, global_config) + + +def run_all_migrations(db, app_config, global_config): + """ + Initializes or migrates a database that already has a + connection setup and also initializes or migrates all + extensions based on the config files. + + It can be used to initialize an in-memory database for + testing. + """ # Gather information from all media managers / projects dbdatas = gather_database_data( - app_config['media_types'], global_config.get('plugins', {}).keys()) - # Set up the database - db = setup_connection_and_db_from_config(app_config, migrations=True) - Session = sessionmaker(bind=db.engine) # Setup media managers for all dbdata, run init/migrate and print info diff --git a/mediagoblin/gmg_commands/import_export.py b/mediagoblin/gmg_commands/import_export.py index d51a1e3e..fbac09f6 100644 --- a/mediagoblin/gmg_commands/import_export.py +++ b/mediagoblin/gmg_commands/import_export.py @@ -16,6 +16,7 @@ from mediagoblin import mg_globals from mediagoblin.db.open import setup_connection_and_db_from_config +from mediagoblin.gmg_commands import util as commands_util from mediagoblin.storage.filestorage import BasicFileStorage from mediagoblin.init import setup_storage, setup_global_and_app_config @@ -63,7 +64,7 @@ def _import_media(db, args): # TODO: Add import of queue files queue_cache = BasicFileStorage(args._cache_path['queue']) - for entry in db.MediaEntry.find(): + for entry in db.MediaEntry.query.filter_by(): for name, path in entry.media_files.items(): _log.info('Importing: {0} - {1}'.format( entry.title.encode('ascii', 'replace'), @@ -204,7 +205,7 @@ def _export_media(db, args): # TODO: Add export of queue files queue_cache = BasicFileStorage(args._cache_path['queue']) - for entry in db.MediaEntry.find(): + for entry in db.MediaEntry.query.filter_by(): for name, path in entry.media_files.items(): _log.info(u'Exporting {0} - {1}'.format( entry.title, @@ -223,6 +224,7 @@ def env_export(args): ''' Export database and media files to a tar archive ''' + commands_util.check_unrecognized_args(args) if args.cache_path: if os.path.exists(args.cache_path): _log.error('The cache directory must not exist ' diff --git a/mediagoblin/gmg_commands/reprocess.py b/mediagoblin/gmg_commands/reprocess.py new file mode 100644 index 00000000..e2f19ea3 --- /dev/null +++ b/mediagoblin/gmg_commands/reprocess.py @@ -0,0 +1,302 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import argparse +import os + +from mediagoblin import mg_globals +from mediagoblin.db.models import MediaEntry +from mediagoblin.gmg_commands import util as commands_util +from mediagoblin.submit.lib import run_process_media +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.tools.pluginapi import hook_handle +from mediagoblin.processing import ( + ProcessorDoesNotExist, ProcessorNotEligible, + get_entry_and_processing_manager, get_processing_manager_for_type, + ProcessingManagerDoesNotExist) + + +def reprocess_parser_setup(subparser): + subparser.add_argument( + '--celery', + action='store_true', + help="Don't process eagerly, pass off to celery") + + subparsers = subparser.add_subparsers(dest="reprocess_subcommand") + + ################### + # available command + ################### + available_parser = subparsers.add_parser( + "available", + help="Find out what actions are available for this media") + + available_parser.add_argument( + "id_or_type", + help="Media id or media type to check") + + available_parser.add_argument( + "--action-help", + action="store_true", + help="List argument help for each action available") + + available_parser.add_argument( + "--state", + help="The state of media you would like to reprocess") + + + ############# + # run command + ############# + + run_parser = subparsers.add_parser( + "run", + help="Run a reprocessing on one or more media") + + run_parser.add_argument( + 'media_id', + help="The media_entry id(s) you wish to reprocess.") + + run_parser.add_argument( + 'reprocess_command', + help="The reprocess command you intend to run") + + run_parser.add_argument( + 'reprocess_args', + nargs=argparse.REMAINDER, + help="rest of arguments to the reprocessing tool") + + + ################ + # thumbs command + ################ + thumbs = subparsers.add_parser( + 'thumbs', + help='Regenerate thumbs for all processed media') + + thumbs.add_argument( + '--size', + nargs=2, + type=int, + metavar=('max_width', 'max_height')) + + ################# + # initial command + ################# + subparsers.add_parser( + 'initial', + help='Reprocess all failed media') + + ################## + # bulk_run command + ################## + bulk_run_parser = subparsers.add_parser( + 'bulk_run', + help='Run reprocessing on a given media type or state') + + bulk_run_parser.add_argument( + 'type', + help='The type of media you would like to process') + + bulk_run_parser.add_argument( + '--state', + default='processed', + nargs='?', + help='The state of the media you would like to process. Defaults to' \ + " 'processed'") + + bulk_run_parser.add_argument( + 'reprocess_command', + help='The reprocess command you intend to run') + + bulk_run_parser.add_argument( + 'reprocess_args', + nargs=argparse.REMAINDER, + help='The rest of the arguments to the reprocessing tool') + + ############### + # help command? + ############### + + +def available(args): + # Get the media type, either by looking up media id, or by specific type + try: + media_id = int(args.id_or_type) + media_entry, manager = get_entry_and_processing_manager(media_id) + media_type = media_entry.media_type + except ValueError: + media_type = args.id_or_type + media_entry = None + manager = get_processing_manager_for_type(media_type) + except ProcessingManagerDoesNotExist: + entry = MediaEntry.query.filter_by(id=args.id_or_type).first() + print 'No such processing manager for {0}'.format(entry.media_type) + + if args.state: + processors = manager.list_all_processors_by_state(args.state) + elif media_entry is None: + processors = manager.list_all_processors() + else: + processors = manager.list_eligible_processors(media_entry) + + print "Available processors:" + print "=====================" + print "" + + if args.action_help: + for processor in processors: + print processor.name + print "-" * len(processor.name) + + parser = processor.generate_parser() + parser.print_help() + print "" + + else: + for processor in processors: + if processor.description: + print " - %s: %s" % (processor.name, processor.description) + else: + print " - %s" % processor.name + + +def run(args, media_id=None): + if not media_id: + media_id = args.media_id + try: + media_entry, manager = get_entry_and_processing_manager(media_id) + + # TODO: (maybe?) This could probably be handled entirely by the + # processor class... + try: + processor_class = manager.get_processor( + args.reprocess_command, media_entry) + except ProcessorDoesNotExist: + print 'No such processor "%s" for media with id "%s"' % ( + args.reprocess_command, media_entry.id) + return + except ProcessorNotEligible: + print 'Processor "%s" exists but media "%s" is not eligible' % ( + args.reprocess_command, media_entry.id) + return + + reprocess_parser = processor_class.generate_parser() + reprocess_args = reprocess_parser.parse_args(args.reprocess_args) + reprocess_request = processor_class.args_to_request(reprocess_args) + run_process_media( + media_entry, + reprocess_action=args.reprocess_command, + reprocess_info=reprocess_request) + + except ProcessingManagerDoesNotExist: + entry = MediaEntry.query.filter_by(id=media_id).first() + print 'No such processing manager for {0}'.format(entry.media_type) + + +def bulk_run(args): + """ + Bulk reprocessing of a given media_type + """ + query = MediaEntry.query.filter_by(media_type=args.type, + state=args.state) + + for entry in query: + run(args, entry.id) + + +def thumbs(args): + """ + Regenerate thumbs for all processed media + """ + query = MediaEntry.query.filter_by(state='processed') + + for entry in query: + try: + media_entry, manager = get_entry_and_processing_manager(entry.id) + + # TODO: (maybe?) This could probably be handled entirely by the + # processor class... + try: + processor_class = manager.get_processor( + 'resize', media_entry) + except ProcessorDoesNotExist: + print 'No such processor "%s" for media with id "%s"' % ( + 'resize', media_entry.id) + return + except ProcessorNotEligible: + print 'Processor "%s" exists but media "%s" is not eligible' % ( + 'resize', media_entry.id) + return + + reprocess_parser = processor_class.generate_parser() + + # prepare filetype and size to be passed into reprocess_parser + if args.size: + extra_args = 'thumb --{0} {1} {2}'.format( + processor_class.thumb_size, + args.size[0], + args.size[1]) + else: + extra_args = 'thumb' + + reprocess_args = reprocess_parser.parse_args(extra_args.split()) + reprocess_request = processor_class.args_to_request(reprocess_args) + run_process_media( + media_entry, + reprocess_action='resize', + reprocess_info=reprocess_request) + + except ProcessingManagerDoesNotExist: + print 'No such processing manager for {0}'.format(entry.media_type) + + +def initial(args): + """ + Reprocess all failed media + """ + query = MediaEntry.query.filter_by(state='failed') + + for entry in query: + try: + media_entry, manager = get_entry_and_processing_manager(entry.id) + run_process_media( + media_entry, + reprocess_action='initial') + except ProcessingManagerDoesNotExist: + print 'No such processing manager for {0}'.format(entry.media_type) + + +def reprocess(args): + # Run eagerly unless explicetly set not to + if not args.celery: + os.environ['CELERY_ALWAYS_EAGER'] = 'true' + + commands_util.setup_app(args) + + if args.reprocess_subcommand == "run": + run(args) + + elif args.reprocess_subcommand == "available": + available(args) + + elif args.reprocess_subcommand == "bulk_run": + bulk_run(args) + + elif args.reprocess_subcommand == "thumbs": + thumbs(args) + + elif args.reprocess_subcommand == "initial": + initial(args) diff --git a/mediagoblin/gmg_commands/theme.py b/mediagoblin/gmg_commands/theme.py deleted file mode 100644 index 71abb982..00000000 --- a/mediagoblin/gmg_commands/theme.py +++ /dev/null @@ -1,122 +0,0 @@ -# GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -import os - -from mediagoblin.init import setup_global_and_app_config -from mediagoblin.tools.theme import register_themes -from mediagoblin.tools.translate import pass_to_ugettext as _ -from mediagoblin.tools.common import simple_printer - - -def theme_parser_setup(subparser): - theme_subparsers = subparser.add_subparsers( - dest=u"subcommand", - help=u'Theme sub-commands') - - # Install command - install_parser = theme_subparsers.add_parser( - u'install', help=u'Install a theme to this mediagoblin instance') - install_parser.add_argument( - u'themefile', help=u'The theme archive to be installed') - - theme_subparsers.add_parser( - u'assetlink', - help=( - u"Link the currently installed theme's assets " - u"to the served theme asset directory")) - - -########### -# Utilities -########### - -def link_assets(theme, link_dir, printer=simple_printer): - """ - Returns a list of string of text telling the user what we did - which should be printable. - """ - link_dir = link_dir.rstrip(os.path.sep) - link_parent_dir = os.path.dirname(link_dir) - - results = [] - - if theme is None: - printer(_("Cannot link theme... no theme set\n")) - return results - - def _maybe_unlink_link_dir(): - """unlink link directory if it exists""" - if os.path.lexists(link_dir) \ - and os.path.islink(link_dir): - os.unlink(link_dir) - return True - - return results - - if theme.get('assets_dir') is None: - printer(_("No asset directory for this theme\n")) - if _maybe_unlink_link_dir(): - printer( - _("However, old link directory symlink found; removed.\n")) - return results - - _maybe_unlink_link_dir() - - # make the link directory parent dirs if necessary - if not os.path.lexists(link_parent_dir): - os.makedirs(link_parent_dir) - - os.symlink( - theme['assets_dir'].rstrip(os.path.sep), - link_dir) - printer("Linked the theme's asset directory:\n %s\nto:\n %s\n" % ( - theme['assets_dir'], link_dir)) - - -def install_theme(install_dir, themefile): - pass # TODO ;) - - -############# -# Subcommands -############# - -def assetlink_command(args): - """ - Link the asset directory of the currently installed theme - """ - global_config, app_config = setup_global_and_app_config(args.conf_file) - theme_registry, current_theme = register_themes(app_config) - link_assets(current_theme, app_config['theme_linked_assets_dir']) - - -def install_command(args): - """ - Handle the 'install this theme' subcommand - """ - global_config, app_config = setup_global_and_app_config(args.conf_file) - install_dir = app_config['theme_install_dir'] - install_theme(install_dir, args.themefile) - - -SUBCOMMANDS = { - 'assetlink': assetlink_command, - 'install': install_command} - - -def theme(args): - SUBCOMMANDS[args.subcommand](args) diff --git a/mediagoblin/gmg_commands/users.py b/mediagoblin/gmg_commands/users.py index 024c8498..4a730d9e 100644 --- a/mediagoblin/gmg_commands/users.py +++ b/mediagoblin/gmg_commands/users.py @@ -15,7 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from mediagoblin.gmg_commands import util as commands_util -from mediagoblin.auth import lib as auth_lib +from mediagoblin import auth from mediagoblin import mg_globals def adduser_parser_setup(subparser): @@ -40,9 +40,9 @@ def adduser(args): db = mg_globals.database users_with_username = \ - db.User.find({ - 'username': args.username.lower(), - }).count() + db.User.query.filter_by( + username=args.username.lower() + ).count() if users_with_username: print u'Sorry, a user with that name already exists.' @@ -52,9 +52,18 @@ def adduser(args): 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.pw_hash = auth.gen_password_hash(args.password) + default_privileges = [ + db.Privilege.query.filter( + db.Privilege.privilege_name==u'commenter').one(), + db.Privilege.query.filter( + db.Privilege.privilege_name==u'uploader').one(), + db.Privilege.query.filter( + db.Privilege.privilege_name==u'reporter').one(), + db.Privilege.query.filter( + db.Privilege.privilege_name==u'active').one() + ] + entry.all_privileges = default_privileges entry.save() print "User created (and email marked as verified)" @@ -71,9 +80,13 @@ def makeadmin(args): db = mg_globals.database - user = db.User.one({'username': unicode(args.username.lower())}) + user = db.User.query.filter_by( + username=unicode(args.username.lower())).one() if user: - user.is_admin = True + user.all_privileges.append( + db.Privilege.query.filter( + db.Privilege.privilege_name==u'admin').one() + ) user.save() print 'The user is now Admin' else: @@ -94,9 +107,10 @@ def changepw(args): db = mg_globals.database - user = db.User.one({'username': unicode(args.username.lower())}) + user = db.User.query.filter_by( + username=unicode(args.username.lower())).one() if user: - user.pw_hash = auth_lib.bcrypt_gen_password_hash(args.password) + user.pw_hash = auth.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 6a6853d5..63e39ca9 100644 --- a/mediagoblin/gmg_commands/util.py +++ b/mediagoblin/gmg_commands/util.py @@ -36,5 +36,5 @@ def prompt_if_not_set(variable, text, password=False): 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 5e69858e..7c3411f7 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 51c71c3a..8c0454d9 100644 --- a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po @@ -3,18 +3,19 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Majid Al-Dharrab <majid@aldharrab.com>, 2011. -# Mena Rezk Eid <minaeid90@gmail.com>, 2013. -# <Omar.w.kh@gmail.com>, 2011. -# <osamak@gnu.org>, 2011. +# Jiyda <jiydam@gmail.com>, 2013 +# Majid Al-Dharrab <majid@aldharrab.com>, 2011 +# minaeid90 <minaeid90@gmail.com>, 2013 +# OmarKH <Omar.w.kh@gmail.com>, 2011 +# OsamaK <osamak@gnu.org>, 2011 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Arabic (http://www.transifex.com/projects/p/mediagoblin/language/ar/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -22,251 +23,262 @@ msgstr "" "Language: ar\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "عÙوًا، التسجيل غير Ù…ØªØ§Ø Ù‡Ù†Ø§." -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "اسم المستخدم" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "كلمة السر" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "عنوان البريد الإلكتروني" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "اسم مستخدم او ايميل غير صØÙŠØ." -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "هذا الØÙ‚Ù„ لا يأخذ ايميل." -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "عÙوًا، التسجيل غير Ù…ØªØ§Ø Ù‡Ù†Ø§." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "هذا الØÙ‚Ù„ ÙŠØØªØ§Ø¬ ايميل." -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "عذرًا، لقد اختار مستخدم آخر هذا الاسم." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." +msgstr "عذرًا، لقد اختار مستخدم آخر هذا الايميل." + +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "تم التØÙ‚Ù‚ من بريدك الإلكتروني. يمكنك الآن الولوج، ÙˆØªØØ±ÙŠØ± ملÙÙƒ الشخصي، ونشر الصور!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Ù…ÙØªØ§Ø التØÙ‚Ù‚ أو معر٠المستخدم خاطئ" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "يجب عليك تسجيل الدخول لإرسال بريد الكترونى لك!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "لقد قمت Ø¨Ø§Ù„ÙØ¹Ù„ بالتØÙ‚Ù‚ من عنوان البريد الإلكتروني الخاص بك!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "أعدنا إرسال رسالة التØÙ‚Ù‚." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "تعذر إرسال رسالة استعادة كلمة السر لأن اسم المستخدم معطل أو لأننا لم نتØÙ‚Ù‚ من بريدك الإلكتروني." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "العنوان" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "وص٠هذا العمل." -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." -msgstr "" +msgstr "بامكانك استخدام âŽ\n<a href=\"http://daringfireball.net/projects/markdown/basics\">âŽ\nMarkdown</a> للإدراج." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "الوسوم" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." -msgstr "" +msgstr "قم Ø¨ÙØµÙ„ Ø§Ù„Ù…ØØ¯Ø¯Ø§Øª Ø¨ÙØµÙ„Ø©." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "المسار" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "لا يمكن ترك المسار ÙØ§Ø±ØºÙ‹Ø§" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." -msgstr "" +msgstr "مقدمة عنوان هذه الميديا, غالبا لن ØªØØªØ§Ø¬ لتغيره." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" -msgstr "" +msgstr "ترخيص" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "السيرة" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "الموقع الإلكتروني" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" -msgstr "" - -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "" +msgstr "العنوان ÙŠØØªÙˆÙŠ Ø¹Ù„Ù‰ اخطاء" -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "" +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "ارسل لي رسالة عندما يقوم الاخرون بالتعليق على الميديا خاصتي" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" -msgstr "" +msgstr "ØªÙØ¶ÙŠÙ„ رخصة" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" +msgstr "سو٠تكون هذه رخصتك المبدئية ÙÙŠ نماذج التØÙ…يل." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" -msgstr "" +msgstr "لا يمكن ترك العنوان ÙØ§Ø±ØºÙ‹Ø§" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" -msgstr "" +msgstr "وص٠هذه المجموعة" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." +msgstr "مقدمة عنوان هذه المجموعة, غالبا لن ØªØØªØ§Ø¬ لتغيره." + +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr " كلمة السر القديمة" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "قم بإدخال رقمك السري القديم ØØªÙ‰ تثبت انك ØµØ§ØØ¨ هذا Ø§Ù„ØØ³Ø§Ø¨." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "رقم سري جديد" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "كلمة السر" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "يوجد مل٠آخر بهذا المسار لدى هذى المستخدم." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "أنت ØªØØ±Ù‘ر وسائط مستخدم آخر. كن ØØ°Ø±Ù‹Ø§ أثناء العملية." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" -msgstr "" +msgstr "لقد قمت Ø¨Ø¥Ø¶Ø§ÙØ© مرÙقة %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." -msgstr "" +msgstr "يمكنك Ùقط تعديل ØØ³Ø§Ø¨Ùƒ الخاص" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "أنت ØªØØ±Ù‘ر مل٠مستخدم آخر. كن ØØ°Ø±Ù‹Ø§ أثناء العملية." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" -msgstr "" +msgstr "تم ØÙظ تغيرات ØØ³Ø§Ø¨Ùƒ" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "كلمة سر خاطئة" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" -msgstr "" +msgstr "تم ØÙظ خصائص ØØ³Ø§Ø¨Ùƒ" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." -msgstr "" +msgstr "يجب عليك تأكيد إلغاء ØØ³Ø§Ø¨Ùƒ." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" -msgstr "" +msgstr "أنت لديك مجموعة تدعى \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." -msgstr "" +msgstr "توجد مجموعة اخرى بهذا المسار لهذا المستخدم." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." +msgstr "أنت تعدل مجموعة مستخدم آخر. كن ØØ°Ø±Ù‹Ø§ أثناء العملية." + +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "كلمة سر خاطئة" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" -msgstr "" +msgstr "لم يتم ربط الثيم... لاتوجد مجموعة ثيمات\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" -msgstr "" +msgstr "لا يوجد مسار جيد لهذا الثيم\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" +msgstr "ولكن, الرابط القديم للمسار الذي تم ايجاده; ØÙذÙ.\n" + +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" msgstr "" #: mediagoblin/meddleware/csrf.py:134 @@ -274,55 +286,246 @@ msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.<br/>Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "CSRF كوكيز غير موجودة, وهذا من الممكن ان يكون نتيجة لمانع الكوكيز او شئ من هذا القبيل.<br/>تأكد من أنك قمت Ø¨Ø§Ù„Ø³Ù…Ø§Ø Ù„Ø®ØµØ§Ø¦Øµ الكوكيز لهذا الميدان." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" +msgstr "عذرا, انا لا ادعم هذا النوع من Ø§Ù„Ù…Ù„ÙØ§Øª :(" + +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" +msgstr "ÙØ´Ù„ ÙÙŠ تØÙˆÙŠÙ„ الÙيديو" + +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "قام بالتعليق على مشاركتك" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "اسم المستخدم" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "عنوان البريد الإلكتروني" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "اسم المستخدم او الايميل" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "إذا كان هذا الايميل(ØØ³Ø§Ø³ Ù„Ù„ØØ±ÙˆÙ الكبيرة والصغيرة!) Ù…ÙØ³Ø¬Ù„, Ùقد تم إرسال ايميل به تعليمات عن كيÙية تغيير رقمك السري." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "لم نتمكن من العثور على Ø£ØØ¯ له أسم المستخدم هذا." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "لقد تم إرسال ايميل به تعليمات عن كيÙية تغيير رقمك السري." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "تعذر إرسال رسالة استعادة كلمة السر لأن اسم المستخدم معطل أو لأننا لم نتØÙ‚Ù‚ من بريدك الإلكتروني." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "تستطيع الآن الدخول باستخدام رقمك السري الجديد." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "قم بضبط رقمك السري الجديد" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "قم بضبط رقم سري" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" msgstr "" +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "ألا تملك ØØ³Ø§Ø¨Ù‹Ø§ بعد؟" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "أنشئ ØØ³Ø§Ø¨Ù‹Ø§ هنا!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "استعادة كلمة السر" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "ارسل تعليمات" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "أنسيت كلمة سرك؟" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" -msgstr "" +msgstr "المكان" #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52 #, python-format msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" +msgstr "عرض ÙÙŠ <a href=\"%(osm_url)s\">OpenStreetMap</a>" + +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" msgstr "" #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" -msgstr "" +msgstr "سماØ" #: mediagoblin/plugins/oauth/forms.py:30 msgid "Deny" -msgstr "" +msgstr "Ø±ÙØ¶" #: mediagoblin/plugins/oauth/forms.py:34 msgid "Name" -msgstr "" +msgstr "الاسم" #: mediagoblin/plugins/oauth/forms.py:35 msgid "The name of the OAuth client" -msgstr "" +msgstr "اسم العميل Ø§Ù„Ù…Ù†Ø´ÙØ¦" #: mediagoblin/plugins/oauth/forms.py:36 msgid "Description" -msgstr "" +msgstr "الوصÙ" #: mediagoblin/plugins/oauth/forms.py:38 msgid "" "This will be visible to users allowing your\n" " application to authenticate as them." -msgstr "" +msgstr "سو٠يكون هذا مرئي بالنسبة للمستخدمين ØØªÙ‰ يتاØ\nللبرنامج خاصتك بالتصديق عليهم." #: mediagoblin/plugins/oauth/forms.py:40 msgid "Type" -msgstr "" +msgstr "النوع" #: mediagoblin/plugins/oauth/forms.py:45 msgid "" @@ -332,252 +535,364 @@ msgid "" " <strong>Public</strong> - The client can't make confidential\n" " requests to the GNU MediaGoblin instance (e.g. client-side\n" " JavaScript client)." -msgstr "" +msgstr "<strong>سري</strong> - يستطيع العميل\nان يقوم بطلب نسخة من GNU MediaGoblin والتي من الممكن ان \nيعترضه وكيل المستخدم (مثلا الخادم من جانب العميل).<br />\n<strong>عام</strong> - لا يستطيع العميل ارسال طلبات سرية\nلنسخة من GNU MediaGoblin (مثلا \nخادم Ø§Ù„Ø¬Ø§ÙØ§ سكريبت من جانب العميل)." #: mediagoblin/plugins/oauth/forms.py:52 msgid "Redirect URI" -msgstr "" +msgstr "تØÙˆÙŠÙ„ لينك" #: mediagoblin/plugins/oauth/forms.py:54 msgid "" "The redirect URI for the applications, this field\n" " is <strong>required</strong> for public clients." -msgstr "" +msgstr "الرابط الموجه للبرنامج, هذا الØÙ‚Ù„\n<strong>مطلوب</strong> لجمهور العملاء." #: mediagoblin/plugins/oauth/forms.py:66 msgid "This field is required for public clients" -msgstr "" +msgstr "هذا الØÙ‚Ù„ مطلوب لجمهور العملاء" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" -msgstr "" +msgstr "العميل {0} تم تسجيله!" #: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 msgid "OAuth client connections" -msgstr "" +msgstr "ارتباطات العميل المنشئ" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "عميلك المنشئ" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" -msgstr "" +msgstr "اضÙ" -#: mediagoblin/processing/__init__.py:172 -msgid "Invalid file given for media type." +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." msgstr "" -#: mediagoblin/submit/forms.py:26 -msgid "File" -msgstr "الملÙ" +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" -#: mediagoblin/submit/views.py:51 -msgid "You must provide a file." -msgstr "يجب أن تضع ملÙًا." +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" -#: mediagoblin/submit/views.py:97 -msgid "Woohoo! Submitted!" -msgstr "يا سلام! Ù†ÙØ´Ø±ÙŽØª!" +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/plugins/openid/views.py:106 #, python-format -msgid "Collection \"%s\" added!" +msgid "Verification of %s failed: %s" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 -msgid "Verify your email!" -msgstr "تأكد من بريدك الإلكترونى!" +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 -msgid "log out" +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "إلغاء" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 #: mediagoblin/templates/mediagoblin/auth/login.html:28 #: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 msgid "Log in" msgstr "تسجيل دخول" -#: mediagoblin/templates/mediagoblin/base.html:79 -#, python-format -msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "ÙØ´Ù„ الولوج!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 -msgid "Change account settings" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 -msgid "Media processing panel" -msgstr "Ù„ÙˆØØ© معالجة الوسائط" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 -msgid "Add media" -msgstr "أض٠وسائط" +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 -#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 -msgid "Create new collection" +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format +#: mediagoblin/plugins/persona/views.py:144 msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +"You can't delete your only Persona email address unless you have a password " +"set." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." +"Sorry, an account is already registered with that Persona email address." msgstr "" -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "استكشÙ" +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "المل٠المعطى لهذا النوع من الميديا غير صØÙŠØ." + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "الملÙ" + +#: mediagoblin/submit/forms.py:41 msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "يجب أن تضع ملÙًا." + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "يا سلام! Ù†ÙØ´Ø±ÙŽØª!" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "تم Ø¥Ø¶Ø§ÙØ© المجموعة \"%s\"!" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "صورة قزم مرتبك" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 #, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +msgid "until %(until_when)s" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Ø£ØØ¯Ø« الوسائط" +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" +msgstr "تأكد من بريدك الإلكترونى!" + +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" +msgstr "تسجيل خروج" + +#: mediagoblin/templates/mediagoblin/base.html:115 +#, python-format +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +msgstr "<a href=\"%(user_url)s\">%(user_name)s</a>'s ØØ³Ø§Ø¨" + +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" +msgstr "تغيير خصائص Ø§Ù„ØØ³Ø§Ø¨" + +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" +msgstr "Ù„ÙˆØØ© معالجة الوسائط" + +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" +msgstr "تسجيل خروج" + +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" +msgstr "أض٠وسائط" + +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" +msgstr "إنشاء مجموعة جديدة" + +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "توجد وسائط ØªØØª المعالجة" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "لا توجد وسائط ØªØØª المعالجة" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Ø£ØØ¯Ø« الوسائط" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "ÙØ´Ù„ت معالجة هذه Ø§Ù„Ù…Ù„ÙØ§Øª:" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Ù…Ø±ØØ¨Ù‹Ø§ يا %(username)sØŒ\n\nإن أردت تغيير كلمة سرك ÙÙŠ غنو ميدياغوبلن ÙØ§ÙØªØ Ø§Ù„ÙˆØµÙ„Ø© التالية ÙÙŠ Ù…ØªØµÙØÙƒ:\n\n%(verification_url)s\n\nإن كنت ترى أن هذه الرسالة وصلتك خطأً ÙØªØ¬Ø§Ù‡Ù„ها واستمتع بØÙŠØ§ØªÙƒ!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "ÙØ´Ù„ الولوج!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "ألا تملك ØØ³Ø§Ø¨Ù‹Ø§ بعد؟" +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "أنشئ ØØ³Ø§Ø¨Ù‹Ø§ هنا!" +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "أنسيت كلمة سرك؟" +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "أنشئ ØØ³Ø§Ø¨Ù‹Ø§!" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "أنشئ" @@ -592,6 +907,62 @@ msgid "" "%(verification_url)s" msgstr "أهلًا يا %(username)sØŒ\n\nØ§ÙØªØ الرابط التالي\nÙÙŠ Ù…ØªØµÙØÙƒ Ù„ØªÙØ¹ÙŠÙ„ ØØ³Ø§Ø¨Ùƒ ÙÙŠ غنو ميدياغوبلن:\n\n%(verification_url)s" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "برعاية <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> مشروع." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "تم النشر ÙˆÙقا Ù„ <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Source code</a> متاØ." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "استكشÙ" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "اهلا, Ù…Ø±ØØ¨Ø§ بك ÙÙŠ موقع MediaGoblin." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +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/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "لكي تضي٠الميديا خاصتك, تضع التعليقات, والمزيد, يجب عليك الدخول Ø¨ØØ³Ø§Ø¨ MediaGoblin الخاص بك." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "ليس لديك ÙˆØ§ØØ¯ ØØªÙ‰ الآن؟ انه سهل!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,18 +972,18 @@ msgstr "شعار ميدياغوبلن" #: mediagoblin/templates/mediagoblin/edit/attachments.html:35 #, python-format msgid "Editing attachments for %(media_title)s" -msgstr "" +msgstr "تعديل المرÙقات Ù„ %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" -msgstr "" +msgstr "مرÙقات" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" -msgstr "" +msgstr "أض٠مرÙقة" #: mediagoblin/templates/mediagoblin/edit/attachments.html:61 #: mediagoblin/templates/mediagoblin/edit/delete_account.html:42 @@ -627,26 +998,32 @@ msgstr "ألغÙ" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "اØÙظ التغييرات" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" -msgstr "" +msgstr "هل تريد ÙØ¹Ù„ا إلغاء المستخدم '%(user_name)s' وكل الميديا/التعليقات المتعلقة به؟" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 msgid "Yes, really delete my account" -msgstr "" +msgstr "نعم, قم بإلغاء ØØ³Ø§Ø¨ÙŠ" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" -msgstr "" +msgstr "Ø§ØØ°Ù نهائيًا" #: mediagoblin/templates/mediagoblin/edit/edit.html:23 #: mediagoblin/templates/mediagoblin/edit/edit.html:35 @@ -658,10 +1035,14 @@ msgstr "ØªØØ±ÙŠØ± %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/edit_account.html:40 #, python-format msgid "Changing %(username)s's account settings" -msgstr "" +msgstr "نغيير %(username)s خصائص Ø§Ù„ØØ³Ø§Ø¨" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" +msgstr "Ø¥Ù„ØºÙ ØØ³Ø§Ø¨ÙŠ" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" msgstr "" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 @@ -675,48 +1056,87 @@ msgstr "ØªØØ±ÙŠØ± %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "ØªØØ±ÙŠØ± مل٠%(username)s الشخصي" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 #: 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/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" -msgstr "" +msgstr "تØÙ…يل" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38 msgid "Original" -msgstr "" +msgstr "أصلي" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:44 msgid "" "Sorry, this audio will not work because \n" "\tyour web browser does not support HTML5 \n" "\taudio." -msgstr "" +msgstr "عذرا, لن يتم تشغيل الصوت لأن âŽ\nÂ»Ù…ØªØµÙØÙƒ لا يدعم HTML5 âŽ\n»صوتيا." #: mediagoblin/templates/mediagoblin/media_displays/audio.html:47 msgid "" "You can get a modern web browser that \n" "\tcan play the audio at <a href=\"http://getfirefox.com\">\n" "\t http://getfirefox.com</a>!" -msgstr "" +msgstr "تستطيع Ø§Ù„ØØµÙˆÙ„ على Ù…ØªØµÙØ ØØ¯ÙŠØ« âŽ\n»يمكنه تشغيل الصوت ÙÙŠ <a href=\"http://getfirefox.com\">âŽ\n» http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" -msgstr "" +msgstr "مل٠أصلي" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:63 msgid "WebM file (Vorbis codec)" +msgstr "مل٠WebM (Vorbic كوديك)" + +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,94 +1145,286 @@ msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media.html:65 #, python-format msgid "Image for %(media_title)s" -msgstr "" +msgstr "صورة Ù„%(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" -msgstr "" +msgstr "منظور" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" -msgstr "" +msgstr "مقدمة" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" -msgstr "" +msgstr "أعلى" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" -msgstr "" +msgstr "جانب" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" -msgstr "" +msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" -msgstr "" +msgstr "تØÙ…يل نموذج" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" -msgstr "" +msgstr "بنية الملÙ" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" -msgstr "" +msgstr "طول الكائن" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." -msgstr "" +msgstr "عذرا, لن يتم تشغيل هذا الÙيديو لأن âŽ\nÂ»Ù…ØªØµÙØÙƒ لا يدعم HTML5 âŽ\n»Ùيديو." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" +msgstr "تستطيع Ø§Ù„ØØµÙˆÙ„ على Ù…ØªØµÙØ ØØ¯ÙŠØ« âŽ\n»يمكنه تشغيل هذا الÙيديو ÙÙŠ <a href=\"http://getfirefox.com\">âŽ\n» http://getfirefox.com</a>!" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "يمكنك متابعة عملية معالجة وسائط معرضك من هنا." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "توجد وسائط ØªØØª المعالجة" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "لا توجد وسائط ØªØØª المعالجة" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "ÙØ´Ù„ت معالجة هذه Ø§Ù„Ù…Ù„ÙØ§Øª:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "لا توجد مداخل ÙØ§Ø´Ù„Ø©!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "آخر 10 تØÙˆÙŠÙ„ات Ù†Ø§Ø¬ØØ©" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "لا يوجد مداخل Ù…ÙØ¹Ø§Ù„جة بعد! " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Ø¥Ø¶Ø§ÙØ© مجموعة" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" -msgstr "" +msgstr "اض٠الميديا الخاصة بك" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:30 #, python-format msgid "%(collection_title)s (%(username)s's collection)" -msgstr "" +msgstr "%(collection_title)s (%(username)s's مجموعة)" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:39 #, python-format msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" -msgstr "" +msgstr "%(collection_title)s بواسطة <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:52 #: mediagoblin/templates/mediagoblin/user_pages/media.html:79 msgid "Edit" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" +msgstr "تعديل" #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 @@ -823,40 +1435,40 @@ msgstr "أتود ØÙ‚ًا ØØ°Ù %(title)s?" #: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31 #, python-format msgid "Really remove %(media_title)s from %(collection_title)s?" -msgstr "" +msgstr "هل تريد ÙØ¹Ù„ا إلغاء %(media_title)s من %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" -msgstr "" +msgstr "إلغاء" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 #, python-format msgid "%(username)s's collections" -msgstr "" +msgstr "%(username)s's مجموعات" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" -msgstr "" +msgstr "<a href=\"%(user_url)s\">%(username)s</a>'s مجموعات" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format msgid "" "Hi %(username)s,\n" "%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n" -msgstr "" +msgstr "اهلا, %(username)s,\n%(comment_author)s قام بالتعليق على مشاركتك (%(comment_url)s) ÙÙŠ %(instance_name)s\n" #: 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:38 #, python-format msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "<a href=\"%(user_url)s\">\n%(username)s\n</a>\n's ميديا Ø¨Ø§Ù„Ù…ØØ¯Ø¯\n<a href=\"%(tag_url)s\">\n%(tag)s\n</a>" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -866,40 +1478,37 @@ msgstr "وسائط <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/media.html:38 #, python-format msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" -msgstr "" +msgstr "■اختيار الميديا بواسطة <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" -msgstr "" +msgstr "أض٠تعليق" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" -msgstr "" +msgstr "اض٠هذا التعليق" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 #, python-format msgid "Add “%(media_title)s†to a collection" -msgstr "" +msgstr "Ø¥Ø¶Ø§ÙØ© “%(media_title)s†لمجموعة" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" -msgstr "" +msgstr "+" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58 msgid "Add a new collection" -msgstr "" +msgstr "Ø¥Ø¶Ø§ÙØ© مجموعة جديدة" #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29 msgid "" @@ -908,178 +1517,235 @@ msgstr "يمكنك متابعة عملية معالجة وسائط معرضك Ù… #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89 msgid "Your last 10 successful uploads" -msgstr "" +msgstr "آخر 10 تØÙ…يلات Ù†Ø§Ø¬ØØ© خاصة بك" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "مل٠%(username)s الشخصي" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "عذرًا، تعذر العثور على مستخدم بهذا الاسم." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "يجب التØÙ‚Ù‚ من البريد الإلكتروني" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "أوشكنا على الانتهاء! ما زال ØØ³Ø§Ø¨Ùƒ Ø¨ØØ§Ø¬Ø© إلى Ø§Ù„ØªÙØ¹ÙŠÙ„." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "ستصلك رسالة إلكترونية خلال Ù„ØØ¸Ø§Øª بها التعليمات." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "إن لم تصل." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "أعد إرسال رسالة التØÙ‚Ù‚" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "سجّل Ø£ØØ¯Ù‡Ù… ØØ³Ø§Ø¨Ù‹Ø§ بهذا الاسم، ولكننا بانتظار Ø§Ù„ØªÙØ¹ÙŠÙ„ ØØªÙ‰ الآن." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "إن كنت أنت ذلك الشخص لكنك Ùقدت رسالة التØÙ‚Ù‚ØŒ يمكنك <a href=\"%(login_url)s\">الولوج</a> وإعادة إرسالها." +msgid "%(username)s's profile" +msgstr "مل٠%(username)s الشخصي" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "هذه زاوية لتخبر الآخرين Ùيها عن Ù†ÙØ³Ùƒ." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "ØØ±Ù‘ÙØ± المل٠الشخصي" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "لم يعبئ هذا العضو بيانات ملÙÙ‡ بعد." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" -msgstr "" +msgstr "ØªØØ¯ÙŠØ¯ مجموعة" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Ø£Ø¸Ù‡ÙØ± كل وسائط %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "هنا ستظهر وسائطك، ولكن يبدو أنك لم تض٠شيئًا بعد." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "لا يبدو أنه توجد أي وسائط هنا ØØªÙ‰ الآن..." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "يجب التØÙ‚Ù‚ من البريد الإلكتروني" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "أوشكنا على الانتهاء! ما زال ØØ³Ø§Ø¨Ùƒ Ø¨ØØ§Ø¬Ø© إلى Ø§Ù„ØªÙØ¹ÙŠÙ„." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "ستصلك رسالة إلكترونية خلال Ù„ØØ¸Ø§Øª بها التعليمات." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "إن لم تصل." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "أعد إرسال رسالة التØÙ‚Ù‚" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "سجّل Ø£ØØ¯Ù‡Ù… ØØ³Ø§Ø¨Ù‹Ø§ بهذا الاسم، ولكننا بانتظار Ø§Ù„ØªÙØ¹ÙŠÙ„ ØØªÙ‰ الآن." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "إن كنت أنت ذلك الشخص لكنك Ùقدت رسالة التØÙ‚Ù‚ØŒ يمكنك <a href=\"%(login_url)s\">الولوج</a> وإعادة إرسالها." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" -msgstr "" +msgstr "(إلغاء)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" -msgstr "" +msgstr "تم تجميعه ÙÙŠ" #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "Ø¥Ø¶Ø§ÙØ© مجموعة" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 msgid "feed icon" -msgstr "" +msgstr "ايقونة تغذية" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23 msgid "Atom feed" -msgstr "" +msgstr "تغذية ذرية" #: mediagoblin/templates/mediagoblin/utils/license.html:25 msgid "All rights reserved" -msgstr "" +msgstr "جميع الØÙ‚وق Ù…ØÙوظة" #: mediagoblin/templates/mediagoblin/utils/pagination.html:39 msgid "↠Newer" -msgstr "" +msgstr "اجددâ†" #: mediagoblin/templates/mediagoblin/utils/pagination.html:45 msgid "Older →" -msgstr "" +msgstr "→اقدم" #: mediagoblin/templates/mediagoblin/utils/pagination.html:48 msgid "Go to page:" -msgstr "" +msgstr "اذهب إلى ØµÙØØ©:" #: mediagoblin/templates/mediagoblin/utils/prev_next.html:28 #: mediagoblin/templates/mediagoblin/utils/prev_next.html:33 msgid "newer" -msgstr "" +msgstr "اجدد" #: mediagoblin/templates/mediagoblin/utils/prev_next.html:39 #: mediagoblin/templates/mediagoblin/utils/prev_next.html:44 msgid "older" +msgstr "اقدم" + +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" msgstr "" #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" -msgstr "" +msgstr "ØªØØ¯Ø¯ ب" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." -msgstr "" +msgstr "لم نستطيع قراءة هذه الصورة." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "ويØÙŠ!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" +msgstr "ØØ¯Ø« خطأ" + +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" msgstr "" -#: mediagoblin/tools/response.py:51 -msgid "Operation not allowed" +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:63 +msgid "Operation not allowed" +msgstr "غير Ù…Ø³Ù…ÙˆØ Ø¨Ù‡Ø°Ù‡ العملية" + +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" -msgstr "" +msgstr "عذرا ديÙ, لا استطيع ترك ØªÙØ¹Ù„ هذا!</p><p>لقد ØØ§ÙˆÙ„ت تشغيل خاصية ليست Ù…Ø³Ù…ÙˆØØ© لك. هل كنت ØªØØ§ÙˆÙ„ إلغاء جميع ØØ³Ø§Ø¨Ø§Øª المستخدمين مجددا؟" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." +msgstr "يبدو أنه لا توجد ØµÙØØ© بهذا العنوان, عذرا</p><p>إذا كنت متأكد من ØµØØ© العنوان, من الممكن أن تكون Ø§Ù„ØµÙØØ© التي ØªØ¨ØØ« عنها قد تم نقلها أو إلغاءها." + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" msgstr "" #: mediagoblin/user_pages/forms.py:23 msgid "Comment" -msgstr "" +msgstr "تعليق" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1088,87 +1754,98 @@ msgstr "أنا متأكد من رغبتي Ø¨ØØ°Ù هذا العمل" #: mediagoblin/user_pages/forms.py:35 msgid "I am sure I want to remove this item from the collection" -msgstr "" +msgstr "أنا متأكد من أنني أريد إلغاء هذه المادة من المجموعة" #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "مجموعة" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" -msgstr "" +msgstr "-- إختار --" #: mediagoblin/user_pages/forms.py:42 msgid "Include a note" +msgstr "إدراج Ù…Ù„Ø§ØØ¸Ø©" + +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" msgstr "" -#: mediagoblin/user_pages/views.py:166 -msgid "Oops, your comment was empty." +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:183 +msgid "Oops, your comment was empty." +msgstr "عذرا, لقد قمت بادخال تعليق ÙØ§Ø±Øº." + +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" -msgstr "" +msgstr "لقد تم إرسال تعليقك!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." -msgstr "" +msgstr "من ÙØ¶Ù„Ùƒ قم Ø¨ÙØØµ المداخل وقم Ø¨Ø§Ù„Ù…ØØ§ÙˆÙ„Ø© مرة أخرى." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" -msgstr "" +msgstr "يجب عليك إختيار أو Ø¥Ø¶Ø§ÙØ© مجموعة" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" -msgstr "" +msgstr "\"%s\" توجد Ø¨Ø§Ù„ÙØ¹Ù„ ÙÙŠ المجموعة \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" -msgstr "" +msgstr "\"%s\" Ø£ÙØ¶ÙŠÙت للمجموعة \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." -msgstr "" +msgstr "لقد قمت بإلغاء الميديا." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." -msgstr "" +msgstr "لم يتم إلغاء الميديا لأنك لم تقم بإختيار انك متأكد من ذلك." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "أنت على وشك ØØ°Ù وسائط مستخدم آخر. كن ØØ°Ø±Ù‹Ø§ أثناء العملية." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." -msgstr "" +msgstr "لقد قمت بإلغاء المادة من المجموعة." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." -msgstr "" +msgstr "لم يتم إلغاء المادة لأنك لم تقم بإختيار انك متأكد من ذلك." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." -msgstr "" +msgstr "أنت على وشك ØØ°Ù مادة من مجموعة مستخدم آخر. كن ØØ°Ø±Ø§." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" -msgstr "" +msgstr "لقد قمت بإلغاء المجموعة \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." -msgstr "" +msgstr "لم يتم إلغاء المجموعة لأنك لم تقم بإختيار انك متأكد من ذلك." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." -msgstr "" +msgstr "أنت على وشك ØØ°Ù مجموعة مستخدم آخر. كن ØØ°Ø±Ø§." diff --git a/mediagoblin/i18n/bg/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/bg/LC_MESSAGES/mediagoblin.mo Binary files differnew file mode 100644 index 00000000..484b62ba --- /dev/null +++ b/mediagoblin/i18n/bg/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/bg/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/bg/LC_MESSAGES/mediagoblin.po new file mode 100644 index 00000000..4d3be4a3 --- /dev/null +++ b/mediagoblin/i18n/bg/LC_MESSAGES/mediagoblin.po @@ -0,0 +1,1847 @@ +# Translations template for PROJECT. +# Copyright (C) 2013 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# +# Translators: +# Yasen Pramatarov <yasen@lindeas.com>, 2013 +msgid "" +msgstr "" +"Project-Id-Version: GNU MediaGoblin\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"Language-Team: Bulgarian (http://www.transifex.com/projects/p/mediagoblin/language/bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 0.9.6\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "Ðеправилно потребителÑко име или е-поща." + +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "" + +#: mediagoblin/auth/tools.py:116 +msgid "Sorry, a user with that name already exists." +msgstr "" + +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 +msgid "Sorry, a user with that email address already exists." +msgstr "" + +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 +msgid "" +"Your email address has been verified. You may now login, edit your profile, " +"and submit images!" +msgstr "" + +#: mediagoblin/auth/views.py:167 +msgid "The verification key or user id is incorrect" +msgstr "" + +#: mediagoblin/auth/views.py:185 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:193 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:203 +msgid "Resent your verification email." +msgstr "" + +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 +#: mediagoblin/user_pages/forms.py:45 +msgid "Title" +msgstr "Заглавие" + +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 +msgid "Description of this work" +msgstr "" + +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "Може да ползвате\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> за форматиране." + +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 +msgid "Tags" +msgstr "Етикети" + +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 +msgid "Separate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 +msgid "Slug" +msgstr "" + +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 +msgid "The slug can't be empty" +msgstr "" + +#: mediagoblin/edit/forms.py:42 +msgid "" +"The title part of this media's address. You usually don't need to change " +"this." +msgstr "" + +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 +#: mediagoblin/templates/mediagoblin/utils/license.html:20 +msgid "License" +msgstr "Лиценз" + +#: mediagoblin/edit/forms.py:52 +msgid "Bio" +msgstr "БиографиÑ" + +#: mediagoblin/edit/forms.py:58 +msgid "Website" +msgstr "" + +#: mediagoblin/edit/forms.py:60 +msgid "This address contains errors" +msgstr "ÐдреÑÑŠÑ‚ Ñъдържа грешки" + +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "" + +#: mediagoblin/edit/forms.py:67 +msgid "Enable insite notifications about events." +msgstr "" + +#: mediagoblin/edit/forms.py:69 +msgid "License preference" +msgstr "" + +#: mediagoblin/edit/forms.py:75 +msgid "This will be your default license on upload forms." +msgstr "" + +#: mediagoblin/edit/forms.py:88 +msgid "The title can't be empty" +msgstr "Заглавието е задължително" + +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 +#: mediagoblin/user_pages/forms.py:48 +msgid "Description of this collection" +msgstr "ОпиÑание на колекциÑта" + +#: mediagoblin/edit/forms.py:97 +msgid "" +"The title part of this collection's address. You usually don't need to " +"change this." +msgstr "" + +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Стара парола" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Ðова парола" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Ðов Ð°Ð´Ñ€ÐµÑ Ð½Ð° е-поща" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Парола" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 +msgid "An entry with that slug already exists for this user." +msgstr "" + +#: mediagoblin/edit/views.py:91 +msgid "You are editing another user's media. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:161 +#, python-format +msgid "You added the attachment %s!" +msgstr "" + +#: mediagoblin/edit/views.py:188 +msgid "You can only edit your own profile." +msgstr "" + +#: mediagoblin/edit/views.py:194 +msgid "You are editing a user's profile. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:210 +msgid "Profile changes saved" +msgstr "Промените в профила Ñа запазени" + +#: mediagoblin/edit/views.py:243 +msgid "Account settings saved" +msgstr "ÐаÑтройките на профила Ñа запазени" + +#: mediagoblin/edit/views.py:277 +msgid "You need to confirm the deletion of your account." +msgstr "" + +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 +#, python-format +msgid "You already have a collection called \"%s\"!" +msgstr "" + +#: mediagoblin/edit/views.py:317 +msgid "A collection with that slug already exists for this user." +msgstr "" + +#: mediagoblin/edit/views.py:332 +msgid "You are editing another user's collection. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "ÐдреÑÑŠÑ‚ на е-пощата ви е проверен." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Грешна парола" + +#: mediagoblin/gmg_commands/assetlink.py:60 +msgid "Cannot link theme... no theme set\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:73 +msgid "No asset directory for this theme\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:76 +msgid "However, old link directory symlink found; removed.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + +#: mediagoblin/meddleware/csrf.py:134 +msgid "" +"CSRF cookie not present. This is most likely the result of a cookie blocker " +"or somesuch.<br/>Make sure to permit the settings of cookies for this " +"domain." +msgstr "" + +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 +msgid "Sorry, I don't support that file type :(" +msgstr "" + +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 +msgid "Video transcoding failed" +msgstr "" + +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "ПотребителÑко име" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "ÐÐ´Ñ€ÐµÑ Ð½Ð° е-поща" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "ПотребителÑко име или е-поща" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "ПотребителÑко име или е-поща" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Вече може да влезете Ñ Ð½Ð¾Ð²Ð°Ñ‚Ð° Ñи парола." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Паролата ви е Ñменена уÑпешно" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Задаване на нова парола" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Задаване на парола" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "ПромÑна паролата на %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "ЗапиÑ" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "ÐÑмате профил?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Създайте Ñи!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "ВъзÑтановÑване на парола" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Изпращане на указаниÑ" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Забравили Ñте паролата Ñи?" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 +msgid "Location" +msgstr "МеÑтоположение" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52 +#, python-format +msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" +msgstr "Разглеждане Ñ <a href=\"%(osm_url)s\">OpenStreetMap</a>" + +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:29 +msgid "Allow" +msgstr "Позволение" + +#: mediagoblin/plugins/oauth/forms.py:30 +msgid "Deny" +msgstr "Забрана" + +#: mediagoblin/plugins/oauth/forms.py:34 +msgid "Name" +msgstr "Име" + +#: mediagoblin/plugins/oauth/forms.py:35 +msgid "The name of the OAuth client" +msgstr "Име на OAuth клиента" + +#: mediagoblin/plugins/oauth/forms.py:36 +msgid "Description" +msgstr "ОпиÑание" + +#: mediagoblin/plugins/oauth/forms.py:38 +msgid "" +"This will be visible to users allowing your\n" +" application to authenticate as them." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:40 +msgid "Type" +msgstr "Вид" + +#: mediagoblin/plugins/oauth/forms.py:45 +msgid "" +"<strong>Confidential</strong> - The client can\n" +" make requests to the GNU MediaGoblin instance that can not be\n" +" intercepted by the user agent (e.g. server-side client).<br />\n" +" <strong>Public</strong> - The client can't make confidential\n" +" requests to the GNU MediaGoblin instance (e.g. client-side\n" +" JavaScript client)." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:52 +msgid "Redirect URI" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:54 +msgid "" +"The redirect URI for the applications, this field\n" +" is <strong>required</strong> for public clients." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:66 +msgid "This field is required for public clients" +msgstr "" + +#: mediagoblin/plugins/oauth/views.py:55 +msgid "The client {0} has been registered!" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 +msgid "OAuth client connections" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 +msgid "Your OAuth clients" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 +#: mediagoblin/templates/mediagoblin/submit/collection.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 +msgid "Add" +msgstr "ДобавÑне" + +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Грешка при проверката на %s: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Проверката е отменена" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "ДобавÑне на OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Изтриване на OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Изтриване" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Вход" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Грешка при влизането" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "" + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "Файл" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "ТрÑбва да предоÑтавите файл" + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" +msgstr "Проверете е-пощата Ñи!" + +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" +msgstr "изход" + +#: mediagoblin/templates/mediagoblin/base.html:115 +#, python-format +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" +msgstr "ПромÑна наÑтройките на профила" + +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" +msgstr "Изход" + +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" +msgstr "Създаване на нова колекциÑ" + +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Влезли Ñте като" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "ПромÑна на данните ви" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Създаване на профил" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Създаване" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "Задвижвано от <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, проект на <a href=\"http://gnu.org/\">GNU</a>." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "Публикувано ÑъглаÑно <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">ИзходниÑÑ‚ код</a> е наличен." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Здравейте и добре дошли в този Ñайт на MediaGoblin!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/logo.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 +msgid "MediaGoblin logo" +msgstr "Лого на MediaGoblin" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:23 +#: mediagoblin/templates/mediagoblin/edit/attachments.html:35 +#, python-format +msgid "Editing attachments for %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 +msgid "Attachments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:57 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 +msgid "Add attachment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:61 +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit.html:41 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:46 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:67 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48 +msgid "Cancel" +msgstr "Отказ" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:63 +#: mediagoblin/templates/mediagoblin/edit/edit.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 +msgid "Save changes" +msgstr "Запазване на промените" + +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "ПромÑна е-пощата на %(username)s" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 +#, python-format +msgid "Really delete user '%(user_name)s' and all related media/comments?" +msgstr "ÐаиÑтина ли да Ñе изтрие потребителÑÑ‚ '%(user_name)s' и вÑички прилежащи файлове и коментари?" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 +msgid "Yes, really delete my account" +msgstr "Да, наиÑтина да Ñе изтрие профилът ми" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 +msgid "Delete permanently" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit.html:35 +#, python-format +msgid "Editing %(media_title)s" +msgstr "Редактиране на %(media_title)s" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40 +#, python-format +msgid "Changing %(username)s's account settings" +msgstr "ПромÑна наÑтройките на профила на %(username)s" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 +msgid "Delete my account" +msgstr "Изтриване на профила ми" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Е-поща" + +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 +#, python-format +msgid "Editing %(collection_title)s" +msgstr "Редактиране на %(collection_title)s" + +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:34 +#, python-format +msgid "Editing %(username)s's profile" +msgstr "Редактиране профила на %(username)s" + +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Ðови коментари" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "ОтбелÑзване на вÑички като прочетени" + +#: mediagoblin/templates/mediagoblin/listings/collection.html:30 +#: mediagoblin/templates/mediagoblin/listings/collection.html:35 +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 +msgid "Download" +msgstr "ИзтеглÑне" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38 +msgid "Original" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:44 +msgid "" +"Sorry, this audio will not work because \n" +"\tyour web browser does not support HTML5 \n" +"\taudio." +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:47 +msgid "" +"You can get a modern web browser that \n" +"\tcan play the audio at <a href=\"http://getfirefox.com\">\n" +"\t http://getfirefox.com</a>!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 +msgid "Original file" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63 +msgid "WebM file (Vorbis codec)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Създадено" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:65 +#, python-format +msgid "Image for %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "Файл PDF" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 +msgid "Perspective" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 +msgid "Front" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 +msgid "Top" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +msgid "Side" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 +msgid "WebGL" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 +msgid "Download model" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 +msgid "File Format" +msgstr "Файлов формат" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 +msgid "Object Height" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 +msgid "" +"Sorry, this video will not work because\n" +" your web browser does not support HTML5 \n" +" video." +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 +msgid "" +"You can get a modern web browser that \n" +" can play this video at <a href=\"http://getfirefox.com\">\n" +" http://getfirefox.com</a>!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "ПоÑледни 10 уÑпешни качваниÑ" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/submit/collection.html:26 +msgid "Add a collection" +msgstr "ДобавÑне на колекциÑ" + +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 +msgid "Add your media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30 +#, python-format +msgid "%(collection_title)s (%(username)s's collection)" +msgstr "%(collection_title)s (ÐºÐ¾Ð»ÐµÐºÑ†Ð¸Ñ Ð½Ð° %(username)s)" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:39 +#, python-format +msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "%(collection_title)s от <a href=\"%(user_url)s\">%(username)s</a>" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:79 +msgid "Edit" +msgstr "Редактиране" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 +#, python-format +msgid "Really delete %(title)s?" +msgstr "ÐаиÑтина ли да Ñе изтрие %(title)s?" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31 +#, python-format +msgid "Really remove %(media_title)s from %(collection_title)s?" +msgstr "ÐаиÑтина ли да Ñе премахне %(media_title)s от %(collection_title)s?" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 +msgid "Remove" +msgstr "Премахване" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 +#, python-format +msgid "%(username)s's collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 +#, python-format +msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38 +#, python-format +msgid "" +"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " +"href=\"%(tag_url)s\">%(tag)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 +#, python-format +msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:38 +#, python-format +msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 +msgid "Add a comment" +msgstr "ДобавÑне на коментар" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 +msgid "Add this comment" +msgstr "ДобавÑне на коментара" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Преглед на коментара" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Добавено" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 +#, python-format +msgid "Add “%(media_title)s†to a collection" +msgstr "ДобавÑне на “%(media_title)s†към колекциÑ" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 +msgid "+" +msgstr "+" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58 +msgid "Add a new collection" +msgstr "ДобавÑне на нова колекциÑ" + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29 +msgid "" +"You can track the state of media being processed for your gallery here." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89 +msgid "Your last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 +#, python-format +msgid "%(username)s's profile" +msgstr "Профил на %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "Редактиране на профила" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "Преглед на колекциите" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Ðужна е проверка на е-пощата" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 +msgid "(remove)" +msgstr "(премахване)" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:21 +msgid "Collected in" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:40 +msgid "Add to a collection" +msgstr "ДобавÑне към колекциÑ" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 +msgid "feed icon" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23 +msgid "Atom feed" +msgstr "ЕмиÑÐ¸Ñ Atom" + +#: mediagoblin/templates/mediagoblin/utils/license.html:25 +msgid "All rights reserved" +msgstr "Ð’Ñички права запазени" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:39 +msgid "↠Newer" +msgstr "↠По-ново" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:45 +msgid "Older →" +msgstr "По-Ñтаро →" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:48 +msgid "Go to page:" +msgstr "Отиване на Ñтраница:" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33 +msgid "newer" +msgstr "по-ново" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44 +msgid "older" +msgstr "по-Ñтаро" + +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/tools/exif.py:83 +msgid "Could not read the image file." +msgstr "" + +#: mediagoblin/tools/response.py:38 +msgid "Oops!" +msgstr "Опа!" + +#: mediagoblin/tools/response.py:39 +msgid "An error occured" +msgstr "Възникна грешка" + +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Ðеправилна заÑвка" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 +msgid "Operation not allowed" +msgstr "ДейÑтвието не е позволено" + +#: mediagoblin/tools/response.py:64 +msgid "" +"Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " +"function that you are not allowed to. Have you been trying to delete all " +"user accounts again?" +msgstr "" + +#: mediagoblin/tools/response.py:72 +msgid "" +"There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" +" the address is correct, maybe the page you're looking for has been moved or" +" deleted." +msgstr "" + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "година" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "меÑец" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "Ñедмица" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "ден" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "чаÑ" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "минута" + +#: mediagoblin/user_pages/forms.py:23 +msgid "Comment" +msgstr "Коментар" + +#: mediagoblin/user_pages/forms.py:25 +msgid "" +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Може да ползвате <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Markdown</a> за форматиране." + +#: mediagoblin/user_pages/forms.py:31 +msgid "I am sure I want to delete this" +msgstr "" + +#: mediagoblin/user_pages/forms.py:35 +msgid "I am sure I want to remove this item from the collection" +msgstr "ÐаиÑтина иÑкам да премахна този Ð·Ð°Ð¿Ð¸Ñ Ð¾Ñ‚ колекциÑта" + +#: mediagoblin/user_pages/forms.py:39 +msgid "Collection" +msgstr "КолекциÑ" + +#: mediagoblin/user_pages/forms.py:40 +msgid "-- Select --" +msgstr "" + +#: mediagoblin/user_pages/forms.py:42 +msgid "Include a note" +msgstr "ДобавÑне на бележка" + +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Може да ползвате\n <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n Markdown</a> за форматиране." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:189 +msgid "Your comment has been posted!" +msgstr "Коментарът ви е публикуван." + +#: mediagoblin/user_pages/views.py:225 +msgid "Please check your entries and try again." +msgstr "" + +#: mediagoblin/user_pages/views.py:265 +msgid "You have to select or add a collection" +msgstr "ТрÑбва да изберете или добавите колекциÑ" + +#: mediagoblin/user_pages/views.py:276 +#, python-format +msgid "\"%s\" already in collection \"%s\"" +msgstr "\"%s\" вече е в колекциÑта \"%s\"" + +#: mediagoblin/user_pages/views.py:282 +#, python-format +msgid "\"%s\" added to collection \"%s\"" +msgstr "\"%s\" е добавено към колекциÑта \"%s\"" + +#: mediagoblin/user_pages/views.py:307 +msgid "You deleted the media." +msgstr "" + +#: mediagoblin/user_pages/views.py:319 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:326 +msgid "You are about to delete another user's media. Proceed with caution." +msgstr "" + +#: mediagoblin/user_pages/views.py:399 +msgid "You deleted the item from the collection." +msgstr "Изтрихте Ð·Ð°Ð¿Ð¸Ñ Ð¾Ñ‚ колекциÑта." + +#: mediagoblin/user_pages/views.py:403 +msgid "The item was not removed because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:411 +msgid "" +"You are about to delete an item from another user's collection. Proceed with" +" caution." +msgstr "" + +#: mediagoblin/user_pages/views.py:443 +#, python-format +msgid "You deleted the collection \"%s\"" +msgstr "Изтрихте колекциÑта \"%s\"" + +#: mediagoblin/user_pages/views.py:450 +msgid "" +"The collection was not deleted because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:458 +msgid "" +"You are about to delete another user's collection. Proceed with caution." +msgstr "" diff --git a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo Binary files differindex 495ef726..d925b836 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 28bdca82..000d84db 100644 --- a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po @@ -3,17 +3,17 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Al fred <devaleitzer@aim.com>, 2011. -# <devaleitzer@aim.com>, 2011. -# <skarbat@gmail.com>, 2012. +# Al fred <devaleitzer@aim.com>, 2011 +# Al fred <devaleitzer@aim.com>, 2011 +# skarbat <skarbat@gmail.com>, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Catalan (http://www.transifex.com/projects/p/mediagoblin/language/ca/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -21,253 +21,264 @@ msgstr "" "Language: ca\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Ho sentim, el registre està desactivat en aquest cas." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "" -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Nom d'usuari" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Contrasenya" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Adreça electrònica" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Nom d'usuari o correu" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Ho sentim, el registre està desactivat en aquest cas." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Lamentablement aquest usuari ja existeix." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Perdó, ja existeix un usuari amb aquesta adreça de correu." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Ja s'ha verificat la vostra adreça electrònica. Ara podeu entrar, editar el vostre perfil i penjar imatge!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "La clau de verificació o la identificació de l'usuari no són correctes." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Has d'estar conectat per saber a qui hem d'enviar el correu!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Ja has verificat la teva adreça de correu!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Torna'm a enviar el correu de verificació" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "S'ha enviat un correu amb instruccions de com cambiar la teva contrasenya" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "No hem pogut enviar el correu de recuperació de contrasenya perquè el teu nom d'usuari és inactiu o bé l'adreça electrònica del teu compte no ha sigut verificada." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Ara et pots conectar amb la teva nova contrasenya." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "TÃtol" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Descripció d'aquest treball." -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Pots utilitzar⎠<a href=\"http://daringfireball.net/projects/markdown/basics\">⎠Markdown</a> per donar-li format" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Etiquetes" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Separa els tags amb comes." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Llimac" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "El llimac no pot ésser buit" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "El tÃtol de l'adreça d'aquest mitjà . Normalment no necessites modificar això." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Llicència" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Biografia" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Lloc web" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Aquesta adreça conté errors" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Contrasenya antiga" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Introdueix la teva contrasenya antiga per comprovar que aquest compte és teu." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Envia'm correu quan d'altres comentin al meu mitjà " #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nova contrasenya" +msgid "Enable insite notifications about events." +msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Envia'm correu quan d'altres comentin al meu mitjà " - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "El tÃtol no pot ser buit" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Descripció d'aquesta col.lecció" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "La part del tÃtol de l'adreça d'aquesta col.lecció. Normalment no cal que canviis això." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Contrasenya antiga" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Introdueix la teva contrasenya antiga per comprovar que aquest compte és teu." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nova contrasenya" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Contrasenya" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Ja existeix una entrada amb aquest llimac per aquest usuari" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Esteu editant fitxers d'un altre usuari. Aneu amb compte." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Esteu editant el perfil d'un usuari. Aneu amb compte" -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Els canvis al perfil s'han guardat" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Contrasenya errònia" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Els detalls del compte s'han guardat" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Ja tens una col.lecció anomenada \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Estas editant la col.lecció d'un altre usuari. Prossegueix amb cautela." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Contrasenya errònia" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "No es pot enllaçar el tema... no hi ha tema establert\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "Tot i aixÃ, l'enllaç antic al directori s'ha trobat; eliminat.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -275,15 +286,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Ho sento, no puc manegar aquest tipus d'arxiu :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "La transformació del vÃdeo ha fallat" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "comentat al teu post" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Nom d'usuari" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Adreça electrònica" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Nom d'usuari o correu" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "S'ha enviat un correu amb instruccions de com cambiar la teva contrasenya" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "No hem pogut enviar el correu de recuperació de contrasenya perquè el teu nom d'usuari és inactiu o bé l'adreça electrònica del teu compte no ha sigut verificada." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Ara et pots conectar amb la teva nova contrasenya." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Estableix la teva nova contrasenya" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Establir contrasenya" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Encara no teniu un compte?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Creeu-ne un aquÃ!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Recuperar contrasenya" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Enviar instruccions" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Has oblidat la teva contrasenya?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Ubicació" @@ -293,6 +491,10 @@ msgstr "Ubicació" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Veure a <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Permetre" @@ -347,7 +549,7 @@ msgstr "La URI de redirecció per les aplicacions, aquest camp\n és msgid "This field is required for public clients" msgstr "Aquest camp és requeriment per a clients públics" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "El client {0} ha sigut enregistrat!" @@ -360,88 +562,357 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Afegir" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Esborrar" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Entra" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Inici de sessió ha fallat!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Aquest tipus de fitxer no és và lid." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Fitxer" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Heu d'escollir un fitxer." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Visca! S'ha enviat!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "S'ha afegit la col.leccio \"%s\"!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Verifica el teu correu electrònic" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Entra" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Modificar els ajustaments del compte" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Quadre de processament de fitxers" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Tots els fitxers" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Mitjans més recents" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Creeu un compte!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Crea" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Hi %(username)s,\n\nto activate your GNU MediaGoblin account, open the following URL in\nyour web browser:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -449,147 +920,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Alliberat segons la <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Codi font</a> disponible." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "Explorar" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Hola, una benvinguda al MediaGoblin!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 msgid "" "This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " "extraordinarily great piece of media hosting software." msgstr "El lloc esta usant <a href=\"http://mediagoblin.org\">MediaGoblin</a>, una gran i extraordinà ria peça de software per allotjar mitjans." -#: mediagoblin/templates/mediagoblin/root.html:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Per afegir el teu propi mitjà , col.locar comentaris, i més, pots conectar-te amb el teu compte MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "No en tens una encara? Es fà cil!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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\">Crear un compte a aquest lloc</a> \no\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Preparar MediaGoblin al teu propi servidor</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Mitjans més recents" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Aqui pots seguir l'estat del mitjà que s'està processant a aquesta instà ncia." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "S'està processant el fitxer" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "No s'està processant cap mitjà " - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "No s'han pogut penjar els següents fitxers:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Sense entrades fallades!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "Les últimes 10 pujades correctes" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Encara no hi ha entrades processades!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Estableix la teva nova contrasenya" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Establir contrasenya" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Recuperar contrasenya" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Enviar instruccions" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" "\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Hola %(username)s,⎠⎠per cambiar la teva contrasenya de GNU MediaGoblin, obre la següent URL al ⎠teu navegador:⎠⎠%(verification_url)s⎠⎠Si creus que hi ha un error, ignora el correu i continua essent⎠un goblin feliç!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Inici de sessió ha fallat!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Encara no teniu un compte?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Creeu-ne un aquÃ!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Has oblidat la teva contrasenya?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Creeu un compte!" - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Crea" +" >Create an account at this site</a>\n" +" or" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" -"\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" "\n" -"%(verification_url)s" -msgstr "Hi %(username)s,\n\nto activate your GNU MediaGoblin account, open the following URL in\nyour web browser:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -603,13 +973,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Editant afegits per a %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -626,12 +996,18 @@ msgstr "Cancel·la" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Desa els canvis" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -642,7 +1018,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Esborrar permanentment" @@ -659,10 +1035,14 @@ msgstr "Edició %(media_title)s " msgid "Changing %(username)s's account settings" msgstr "Modificant els detalls del compte de %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -674,6 +1054,39 @@ msgstr "Editant %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Editant perfil de %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -684,8 +1097,8 @@ msgstr "Mitjà marcat amb: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Descarregar" @@ -708,7 +1121,8 @@ msgid "" msgstr "Pots obtenir un navegador web modern que \n »podrà reproduir l'à udio, a <a href=\"http://getfirefox.com\">\n » http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Arxiu original" @@ -716,6 +1130,11 @@ msgstr "Arxiu original" msgid "WebM file (Vorbis codec)" msgstr "Arxiu WebM (Vorbis codec)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -726,70 +1145,267 @@ msgstr "Arxiu WebM (Vorbis codec)" msgid "Image for %(media_title)s" msgstr "Imatge per %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "Arxiu WebM (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Aqui pots seguir l'estat del mitjà que s'està processant a aquesta instà ncia." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "S'està processant el fitxer" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "No s'està processant cap mitjà " + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "No s'han pogut penjar els següents fitxers:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Sense entrades fallades!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Les últimes 10 pujades correctes" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Encara no hi ha entrades processades!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Afegir a la col.lecció" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Afegeix el teu mitjà " @@ -808,11 +1424,6 @@ msgstr "%(collection_title)s per a <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "Editar" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Esborrar" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -824,7 +1435,7 @@ msgstr "Realment vols esborrar %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Relment eliminar %(media_title)s de %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Eliminar" @@ -867,24 +1478,21 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Navegant mitjà per a <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Afegeix un comentari" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Afegir aquest comentari" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "a" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Afegit el</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -909,85 +1517,107 @@ msgstr "Aqui pots seguir l'estat del mitjà que s'està processant per la teva g msgid "Your last 10 successful uploads" msgstr "Les teves 10 últimes pujades correctes" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Perfil de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Lamentablement no s'ha trobat l'usuari que cercà veu." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Cal que verifiqueu l'adreça electrònica" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Gairebé esteu! Tan sols falta que activeu el vostre compte" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Us hauria d'arribar un correu amb les instruccions per a fer-ho." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Per si no hi fos:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Torna'm a enviar el correu de verificació" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Algú ja ha registrat un compte amb aquest nom d'usuari, però encara l'ha d'activar." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Si siu aqeust usuari però heu perdut el correu de verificació, podeu <a href=\"%(login_url)s\">entrar</a> i tornar-lo a enviar." +msgid "%(username)s's profile" +msgstr "Perfil de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Aqui hi ha un espai per explicar de tu als demés" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Edita el perfil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Aquest usuari encara no ha escrit res al seu perfil." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "View all of %(username)s's media" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Aqui és on apareixerà el teu mitjà , però sembla que encara no hi has afegit res." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Sembla que no hi ha cap mitjà aqui encara..." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Cal que verifiqueu l'adreça electrònica" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Gairebé esteu! Tan sols falta que activeu el vostre compte" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Us hauria d'arribar un correu amb les instruccions per a fer-ho." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Per si no hi fos:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Torna'm a enviar el correu de verificació" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Algú ja ha registrat un compte amb aquest nom d'usuari, però encara l'ha d'activar." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Si siu aqeust usuari però heu perdut el correu de verificació, podeu <a href=\"%(login_url)s\">entrar</a> i tornar-lo a enviar." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1036,50 +1666,85 @@ msgstr "més nou" msgid "older" msgstr "més antic" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "No s'ha pogut llegir l'arxiu d'imatge" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Ups!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Pots usar <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> per donar format." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1101,73 +1766,84 @@ msgstr "-- Sel.leccionar --" msgid "Include a note" msgstr "Incluir una nota" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "comentat al teu post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Uups, el teu comentari era buit." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "El teu comentari s'ha publicat!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "Si et plau, comprova les teves entrades i intenta-ho de nou." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Has de sel.leccionar o afegir una col.lecció" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" ja és a la col.lecció \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" afegir a la col.lecció \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Has esborrat el mitjà " -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "El mitjà no s'ha esborrat perque no has marcat que n'estiguessis segur." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Ets a punt d'esborrar el mitjà d'un altre usuari. Prossegueix amb cautela." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Has esborrat l'element de la col.lecció" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "L'element no s'ha eliminat perque no has marcat que n'estiguessis segur." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Ets a punt d'esborrar un element de la col.lecció d'un altre usuari. Prossegueix amb cautela." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Has esborrat la col.lecció \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "La col.lecció no s'ha esborrat perquè no has marcat que n'estiguessis segur." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Ets a punt d'esborrar la col.lecció d'un altre usuari. Prossegueix amb cautela." diff --git a/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mo Binary files differindex 6b6827f0..b78e483e 100644 --- a/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po index 8494aa60..bece988b 100644 --- a/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po @@ -3,17 +3,18 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Morten Juhl-Johansen Zölde-Fejér <morten@writtenandread.net>, 2012. -# Olle Jonsson <olle.jonsson@gmail.com>, 2012. -# Tanja Trudslev <tanja.trudslev@gmail.com>, 2012. +# Aputsiaĸ Niels Janussen <aj@isit.gl>, 2013 +# Morten Juhl-Johansen Zölde-Fejér <morten@writtenandread.net>, 2012 +# Olle Jonsson <olle.jonsson@gmail.com>, 2012 +# ttrudslev <tanja.trudslev@gmail.com>, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Danish (http://www.transifex.com/projects/p/mediagoblin/language/da/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -21,276 +22,478 @@ msgstr "" "Language: da\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Desværre, registrering er ikke muligt pÃ¥ denne instans" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Brugernavn" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "Beklager, godkendelse er slÃ¥et fra pÃ¥ denne instans." -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Kodeord" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Email adresse" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "Ugyldigt brugernavn eller e-mailadresse." -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Brugernavn eller email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "Dette felt accepterer ikke e-mailadresser." -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Desværre, registrering er ikke muligt pÃ¥ denne instans" +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "Dette felt kræver en e-mailadresse." -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Desværre, det brugernavn er allerede brugt" -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Desværre, en bruger er allerede oprettet for den email" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "Nøglen til bekræftigelse eller bruger-id er ugyldigt." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Din email adresse er blevet bekræftet. Du kan nu logge pÃ¥, ændre din profil, og indsende billeder!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Bekræftelsesnøglen eller brugerid er forkert" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Du er nødt til at være logget ind, sÃ¥ vi ved hvem vi skal emaile!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Du har allerede bekræftet din email adresse!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Email til godkendelse sendt igen." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "En email er blevet sendt med instruktioner til at ændre dit kodeord." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Vi kunne ikke sende en kodeords nulstillings email da dit brugernavn er inaktivt, eller din konto's email adresse er ikke blevet godkendt." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Du kan nu logge ind med dit nye kodeord." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titel" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Beskrivelse af arbejdet" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Du kan bruge\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> til formattering." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Tags" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Separer tags med kommaer." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" -msgstr "" +msgstr "Webnavn" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" -msgstr "" +msgstr "Webnavnet kan ikke stÃ¥ tomt" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Titeldelen af dette medie's adresse. Du behøver normalt ikke ændre dette." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Licens" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Websted" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Denne adresse indeholder fejl" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Gammelt kodeord" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Skriv dit gamle kodeord for at bevise det er din konto." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Email mig nÃ¥r andre kommenterer pÃ¥ mine medier" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Ny kodeord" +msgid "Enable insite notifications about events." +msgstr "Aktivér insite-notifikationer for begivenheder." -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" -msgstr "" +msgstr "Præferencer for licens" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" +msgstr "Dette vil blive dit standardlicens i formularer til overførsler." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Email mig nÃ¥r andre kommenterer pÃ¥ mine medier" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "Titlen kan ikke være tom" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Beskrivelse af denne samling" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "Titeldelen af denne samlings's adresse. Du behøver normalt ikke ændre dette." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Gammelt kodeord" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Skriv dit gamle kodeord for at bevise det er din konto." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Ny kodeord" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Ny e-mailadresse" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Kodeord" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Angiv dit kodeord for at bevise at du ejer denne konto." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." -msgstr "" +msgstr "Et post med dette webnavn findes allerede for denne bruger." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Du er ved at ændre en anden brugers' medier. Pas pÃ¥." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" -msgstr "" +msgstr "Du tilføjede den vedhæftede fil %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." -msgstr "" +msgstr "Du kan kun redigere din egen profil." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Du er ved at ændre en bruger's profil. Pas pÃ¥." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Profilændringer gemt" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Forkert kodeord" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Kontoindstillinger gemt" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." -msgstr "" +msgstr "Du skal bekræfte at du vil slette din konto." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Du har allerede en samling ved navn \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." -msgstr "" +msgstr "En samling med dette webnavn findes allerede for denne bruger." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Du er ved at ændre en anden bruger's samling. Pas pÃ¥." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Din e-mailadresse er blevet bekræftet." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Forkert kodeord" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Kan ikke linke til tema... intet tema sat\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "Springer over \"%s\"; allerede konfigureret.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "Gammel henvisning fundet for \"%s\"; fjerner.\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.<br/>Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "CSRF-cookie er ikke tilstede. Dette skyldes højest sandsynligt en blokering af cookie eller lignende.<br/>Sørg for at tillade, at der angives cookie'er for dette domæne." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Desværre, jeg understøtter ikke den filtype :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "unoconv kunne ikke køres, tjek logfilen" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" +msgstr "Omkodning af video mislykkedes" + +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "kommenterede pÃ¥ dit opslag" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "Abonnerede pÃ¥ kommentarer pÃ¥ %s!" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "Du vil ikke modtage notifikationer for kommentarer pÃ¥ %s." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "Der skal angives en oauth_token." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." msgstr "" +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Brugernavn" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Email adresse" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Brugernavn eller e-mail" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "Forbliv logget ind" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Brugernavn eller email" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "En email er blevet sendt med instruktioner til at ændre dit kodeord." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Vi kunne ikke sende en kodeords nulstillings email da dit brugernavn er inaktivt, eller din konto's email adresse er ikke blevet godkendt." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "Bruger-id er ugyldigt." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Du kan nu logge ind med dit nye kodeord." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Ændringen af din adgangskode blev gennemført" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Angiv dit nye kodeord" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Angiv kodeord" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Ændrer %(username)s's kodeord" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Gem" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Har du endnu ikke en konto?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Opret én her!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Generhverv dit kodeord" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Send instruktioner" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Glemt dit kodeord?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" -msgstr "" +msgstr "Placering" #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52 #, python-format msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" +msgstr "Vis pÃ¥ <a href=\"%(osm_url)s\">OpenStreetMap</a>" + +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" msgstr "" #: mediagoblin/plugins/oauth/forms.py:29 @@ -331,11 +534,11 @@ msgid "" " <strong>Public</strong> - The client can't make confidential\n" " requests to the GNU MediaGoblin instance (e.g. client-side\n" " JavaScript client)." -msgstr "" +msgstr "<strong>Fortrolig</strong> - Klienten kan foretage\n forespørgsler GNU MediaGoblin-instansen, der ikke kan\n opsnappes af brugeren (dvs. serverside-klienten).<br />\n <strong>Offentlig</strong> - Klienten kan ikke foretage fortrolige\n forespørgsler til GNU MediaGoblin-instansen (dvs. JavaScript-klient\n pÃ¥ klientsiden)." #: mediagoblin/plugins/oauth/forms.py:52 msgid "Redirect URI" -msgstr "" +msgstr "Omdirigér URI" #: mediagoblin/plugins/oauth/forms.py:54 msgid "" @@ -347,238 +550,350 @@ msgstr "" msgid "This field is required for public clients" msgstr "Dette felt er nødvendigt for offentlige klienter" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Klienten {0} er blevet registreret!" #: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 msgid "OAuth client connections" -msgstr "" +msgstr "OAuth-klientforbindelser" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "Dine OAuth-klienter" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" -msgstr "" +msgstr "Tilføj" -#: mediagoblin/processing/__init__.py:172 -msgid "Invalid file given for media type." -msgstr "Forkert fil for medietypen." +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "Beklager, der er allerede tilmeldt en konto med dette OpenID." -#: mediagoblin/submit/forms.py:26 -msgid "File" -msgstr "Fil" +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" -#: mediagoblin/submit/views.py:51 -msgid "You must provide a file." -msgstr "Du mÃ¥ give mig en fil" +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "Beklager, OpenID-serveren blev ikke fundet" -#: mediagoblin/submit/views.py:97 -msgid "Woohoo! Submitted!" -msgstr "Juhuu! Delt!" - -#: mediagoblin/submit/views.py:146 +#: mediagoblin/plugins/openid/views.py:61 #, python-format -msgid "Collection \"%s\" added!" -msgstr "" +msgid "No OpenID service was found for %s" +msgstr "Der blev ikke fundet en OpenID-tjeneste for %s" -#: mediagoblin/templates/mediagoblin/base.html:64 -msgid "Verify your email!" -msgstr "Bekræft din email!" +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Verifikation af %s mislykkedes: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Verifikation blev annulleret" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "Din OpenID-url blev glemt." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "Du kan ikke slette din eneste OpenID-url, medmindre du har angivet en adgangskode" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "Denne OpenID er ikke registreret for denne konto." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "Fjernelse af OpenID blev gennemført." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Tilføj et OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Slet et OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Slet" -#: mediagoblin/templates/mediagoblin/base.html:65 -msgid "log out" -msgstr "" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "OpenID'er" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 #: mediagoblin/templates/mediagoblin/auth/login.html:28 #: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 msgid "Log in" msgstr "Log ind" -#: mediagoblin/templates/mediagoblin/base.html:79 -#, python-format -msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" -msgstr "" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Login mislykkedes!" -#: mediagoblin/templates/mediagoblin/base.html:86 -msgid "Change account settings" -msgstr "" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "Log ind for at oprette en konto!" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 -msgid "Media processing panel" -msgstr "" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "Eller log ind med et kodeord!" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" -msgstr "" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "Eller log ind med OpenID!" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 -msgid "Add media" -msgstr "" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "Eller tilmeld dig med OpenID!" -#: mediagoblin/templates/mediagoblin/base.html:99 -#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 -msgid "Create new collection" +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format +#: mediagoblin/plugins/persona/views.py:144 msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." +"You can't delete your only Persona email address unless you have a password " +"set." msgstr "" -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Udforsk" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Hey, velkommen til denne MediaGoblin side!" - -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/plugins/persona/views.py:176 msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +"Sorry, an account is already registered with that Persona email address." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." -msgstr "For at tilføje dine egne medier, skrive kommentarer, og mere, du kan logge ind med din MediaGoblin konto." +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Din e-postadresse for Persona blev gemt." -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" -msgstr "Har du ikke en endnu? Det er let!" +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "Forkert fil for medietypen." + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "Fil" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "Du mÃ¥ give mig en fil" + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "Juhuu! Delt!" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "Samlingen \"%s\" blev tilføjet!" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" +msgstr "Bekræft din email!" + +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" +msgstr "log ud" + +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +msgstr "<a href=\"%(user_url)s\">%(user_name)s</a>'s konto" + +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" +msgstr "Skift kontoindstillinger" + +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" +msgstr "Panel til mediebehandling" + +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" +msgstr "Log ud" + +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" +msgstr "Tilføj medie" + +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" +msgstr "Opret ny samling" + +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Har du endnu ikke en konto?" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Seneste mediefil" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Opret en her!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Godkendelse" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "Godkend" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Du er logget ind som" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "Ønsker du at godkende" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "et ukendt program" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "for at tilgÃ¥ din konto?" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Programmer med adgang til din konto kan:" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "Afsend nyt medie som dig selv" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "Se dine informationer (dvs. profil, medie, osv.)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "Tilpas dine informationer" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "Godkendelse er afsluttet" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "Godkendelse er udført" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Kopiér og indsæt dette i din klient:" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "Opret en konto!" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" -msgstr "" +msgstr "Opret" #: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 #, python-format @@ -589,8 +904,64 @@ msgid "" "your web browser:\n" "\n" "%(verification_url)s" +msgstr "Hej %(username)s,\n\nfor at aktivere din GNU MediaGoblin-konto, Ã¥bner du følgende\nadresse i din webbrowser:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "Drevet af <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, et <a href=\"http://gnu.org/\">GNU</a>-projekt." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "Udgivet under licenset <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Kildekoden</a> er tilgængelig." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Udforsk" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Hey, velkommen til denne MediaGoblin side!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "Dette sted kører <a href=\"http://mediagoblin.org\">MediaGoblin</a>, et særdeles godt stykke software til hosting af medier." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "For at tilføje dine egne medier, skrive kommentarer, og mere, du kan logge ind med din MediaGoblin konto." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "Har du ikke en endnu? Det er let!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "\n >Opret en konto pÃ¥ dette sted</a>\n eller" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Opsæt MediaGoblin pÃ¥ din egen server</a>" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -600,18 +971,18 @@ msgstr "MediaGoblin logo" #: mediagoblin/templates/mediagoblin/edit/attachments.html:35 #, python-format msgid "Editing attachments for %(media_title)s" -msgstr "" +msgstr "Redigerer vedhæftede filer for %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" -msgstr "" +msgstr "Vedhæftede filer" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" -msgstr "" +msgstr "Tilføj en vedhæftet fil" #: mediagoblin/templates/mediagoblin/edit/attachments.html:61 #: mediagoblin/templates/mediagoblin/edit/delete_account.html:42 @@ -626,12 +997,18 @@ msgstr "Afbryd" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Gem ændringer" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Ændrer %(username)ss e-mail" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -639,34 +1016,38 @@ msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 msgid "Yes, really delete my account" -msgstr "" +msgstr "Ja, min konto skal slettes" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" -msgstr "" +msgstr "Slet permanent" #: mediagoblin/templates/mediagoblin/edit/edit.html:23 #: mediagoblin/templates/mediagoblin/edit/edit.html:35 #, python-format msgid "Editing %(media_title)s" -msgstr "" +msgstr "Redigerer %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/edit_account.html:28 #: mediagoblin/templates/mediagoblin/edit/edit_account.html:40 #, python-format msgid "Changing %(username)s's account settings" -msgstr "" +msgstr "Ændrer %(username)s's kontoindstillinger" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" -msgstr "" +msgstr "Slet min konto" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "E-mail" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" -msgstr "" +msgstr "Redigerer %(collection_title)s" #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:34 @@ -674,48 +1055,87 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "Redigerer %(username)s profil" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "Hej,\n\nVi vil gerne sikre, at du er %(username)s. Er dette tilfældet, sÃ¥ følg\nvenligst henvisningen nedenfor, for at bekræfte din nye e-postadresse.\n\n%(verification_url)s\n\nHvis du ikke er %(username)s, eller ikke har forespurgt ændring af e-post, kan du ignorere denne e-mail." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Nye kommentarer" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)s siden" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Markér alle som læst" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr "Medie mærket med: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" -msgstr "" +msgstr "Hent" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38 msgid "Original" -msgstr "" +msgstr "Original" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:44 msgid "" "Sorry, this audio will not work because \n" "\tyour web browser does not support HTML5 \n" "\taudio." -msgstr "" +msgstr "Beklager, denne lydfil vil ikke fungere, fordi \n\tdin webbrowser ikke understøtter \n\tHTML5-lyd." #: mediagoblin/templates/mediagoblin/media_displays/audio.html:47 msgid "" "You can get a modern web browser that \n" "\tcan play the audio at <a href=\"http://getfirefox.com\">\n" "\t http://getfirefox.com</a>!" -msgstr "" +msgstr "Du kan hente en moderne webbrowser som \n\tkan afspille lyden pÃ¥ <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" -msgstr "" +msgstr "Original fil" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:63 msgid "WebM file (Vorbis codec)" -msgstr "" +msgstr "WebM-fil (Vorbis-indkodning)" + +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Oprettet" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -724,273 +1144,484 @@ msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media.html:65 #, python-format msgid "Image for %(media_title)s" -msgstr "" +msgstr "Bilelde for %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF-fil" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" -msgstr "" +msgstr "Perspektiv" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" -msgstr "" +msgstr "Forside" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" -msgstr "" +msgstr "Top" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" -msgstr "" +msgstr "Side" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" -msgstr "" +msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" -msgstr "" +msgstr "Hent model" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" -msgstr "" +msgstr "Filformat" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" -msgstr "" +msgstr "Objektets højde" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." -msgstr "" +msgstr "Beklager, denne video vil ikke fungere, da\ndin webbrowser ikke understøtter HTML5-\nvideoer." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "WebM-fil (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Her kan du følge status for mediet, der bliver behandlet pÃ¥ denne instans." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Mediet er under behandling" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Intet medie er under behandling" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Disse overførsler kunne ikke behandles:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Ingen mislykkede poster!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Seneste 10 succesfulde overførsler" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Ingen behandlede poster, endnu!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" -msgstr "" +msgstr "Tilføj en samling" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" -msgstr "" +msgstr "Tilføj dit medie" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:30 #, python-format msgid "%(collection_title)s (%(username)s's collection)" -msgstr "" +msgstr "%(collection_title)s (%(username)s's samling)" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:39 #, python-format msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" -msgstr "" +msgstr "%(collection_title)s fra <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:52 #: mediagoblin/templates/mediagoblin/user_pages/media.html:79 msgid "Edit" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" +msgstr "Redigér" #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format msgid "Really delete %(title)s?" -msgstr "" +msgstr "Sikker pÃ¥ at du vil slette %(title)s?" #: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31 #, python-format msgid "Really remove %(media_title)s from %(collection_title)s?" -msgstr "" +msgstr "Sikker pÃ¥ at du vil fjerne %(media_title)s fra %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" -msgstr "" +msgstr "Fjern" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 #, python-format msgid "%(username)s's collections" -msgstr "" +msgstr "%(username)ss samlinger" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" -msgstr "" +msgstr "<a href=\"%(user_url)s\">%(username)s</a>s samlinger" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format msgid "" "Hi %(username)s,\n" "%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n" -msgstr "" +msgstr "Hej %(username)s,\n%(comment_author)s kommenterede dit opslag, (%(comment_url)s) pÃ¥ %(instance_name)s\n" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 #, python-format msgid "%(username)s's media" -msgstr "" +msgstr "%(username)s's medie" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38 #, python-format msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "<a href=\"%(user_url)s\">%(username)s</a>s medie med mærket <a href=\"%(tag_url)s\">%(tag)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" -msgstr "" +msgstr "<a href=\"%(user_url)s\">%(username)s</a>s mediefil" #: mediagoblin/templates/mediagoblin/user_pages/media.html:38 #, python-format msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" -msgstr "" +msgstr "â– Gennemser medier fra <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" -msgstr "" +msgstr "Tilføj en kommentar" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" -msgstr "" +msgstr "Tilføj denne kommentar" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "ForhÃ¥ndsvisning af kommentar" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Tilføjet" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 #, python-format msgid "Add “%(media_title)s†to a collection" -msgstr "" +msgstr "Tilføj “%(media_title)s†til en samling" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" -msgstr "" +msgstr "+" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58 msgid "Add a new collection" -msgstr "" +msgstr "Tilføj en ny samling" #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29 msgid "" "You can track the state of media being processed for your gallery here." -msgstr "" +msgstr "Du kan følge tilstanden for mediet som behandles til dit galleri her." #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89 msgid "Your last 10 successful uploads" -msgstr "" +msgstr "Dine seneste 10 succesfulde overførsler" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Desværre, fandt ikke den bruger." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Næsten færdig! Din konto skal stadig aktiveres." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Der skulle komme email om et par øjeblikke med instrukser om hvordan." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Hvis det ikke gør:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Gensend verificeringsemail" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "" +msgid "%(username)s's profile" +msgstr "%(username)s's profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Her kan du fortælle andre om dig selv." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Ret profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." -msgstr "" +msgstr "Brugeren har ikke udfyldt sin profil (endnu)." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" -msgstr "" +msgstr "Gennemse samlinger" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" -msgstr "" +msgstr "Vis alle %(username)s's mediefiler" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." -msgstr "" +msgstr "Her bliver dine medier vist, men det ser ikke ud til at du har tilføjet noget endnu." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." -msgstr "" +msgstr "Der ser ikke ud til at være nogen mediefiler her endnu ..." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Der kræves godkendelse af e-mail" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Næsten færdig! Din konto skal stadig aktiveres." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Der skulle komme email om et par øjeblikke med instrukser om hvordan." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Hvis det ikke gør:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Gensend verificeringsemail" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Nogen har tilmeldt en konto med dette brugernavn, men den mangler stadig at blive aktiveret." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Hvis du er denne person, men har mistet godkendelsesbeskeden, sÃ¥ kan du <a href=\"%(login_url)s\">logge ind</a> og sende den pÃ¥ny." #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" -msgstr "" +msgstr "(fjern)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" @@ -998,176 +1629,222 @@ msgstr "" #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "Tilføj til en samling" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 msgid "feed icon" -msgstr "" +msgstr "Kilde-ikon" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23 msgid "Atom feed" -msgstr "" +msgstr "Atom-kilde" #: mediagoblin/templates/mediagoblin/utils/license.html:25 msgid "All rights reserved" -msgstr "" +msgstr "Alle rettigheder forbeholdes" #: mediagoblin/templates/mediagoblin/utils/pagination.html:39 msgid "↠Newer" -msgstr "" +msgstr "↠Nyere" #: mediagoblin/templates/mediagoblin/utils/pagination.html:45 msgid "Older →" -msgstr "" +msgstr "Ældre →" #: mediagoblin/templates/mediagoblin/utils/pagination.html:48 msgid "Go to page:" -msgstr "" +msgstr "GÃ¥ til side:" #: mediagoblin/templates/mediagoblin/utils/prev_next.html:28 #: mediagoblin/templates/mediagoblin/utils/prev_next.html:33 msgid "newer" -msgstr "" +msgstr "nyere" #: mediagoblin/templates/mediagoblin/utils/prev_next.html:39 #: mediagoblin/templates/mediagoblin/utils/prev_next.html:44 msgid "older" +msgstr "ældre" + +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" msgstr "" #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" -msgstr "" +msgstr "Mærket med" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." -msgstr "" +msgstr "Kunne ikke indlæse billedfilen." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Hovsa!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" -msgstr "" +msgstr "Der opstod en fejl" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Forkert forespørgsel" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "Forespørgslen som blev sendt til serveren er ugyldig, tjek den venligst ekstra grundigt" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" -msgstr "" +msgstr "Handlingen er ikke tilladt" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" -msgstr "" +msgstr "Beklager Søren, jeg kan ikke lade dig gøre det!</p><p>Du har forsøgt at udføre en funktion som du ikke har lov til at foretage. Har du nu forsøgt at slette alle brugerkontiene igen?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "Ã¥r" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "mÃ¥ned" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "uge" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "dag" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "time" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minut" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" -msgstr "" +msgstr "Kommentar" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "" +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Du kan anvende <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Markdown</a> til formatering." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" -msgstr "" +msgstr "Jeg er sikker pÃ¥ at jeg vil slette dette" #: mediagoblin/user_pages/forms.py:35 msgid "I am sure I want to remove this item from the collection" -msgstr "" +msgstr "Jeg er helt sikker pÃ¥ at jeg vil fjerne dette element fra samlingen" #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "Samling" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" -msgstr "" +msgstr "-- Vælg --" #: mediagoblin/user_pages/forms.py:42 msgid "Include a note" -msgstr "" +msgstr "Inkludér en note" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Du kan anvende\n <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n Markdown</a> til formatering." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Beklager, kommentarer er slÃ¥et fra." + +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." -msgstr "" +msgstr "Uups, din kommentar var uden indhold." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" -msgstr "" +msgstr "Din kommentar er blevet slÃ¥et op!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." -msgstr "" +msgstr "Tjek venligst dine poster og forsøg igen." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" -msgstr "" +msgstr "Du skal vælge eller tilføje en samling" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" -msgstr "" +msgstr "\"%s\" er allerede i samlingen \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" -msgstr "" +msgstr "\"%s\" blev tiløføjet til samlingen \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." -msgstr "" +msgstr "Du slettede mediet." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." -msgstr "" +msgstr "Mediet blev ikke slettet, fordi du ikke markerede at du var sikker." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." -msgstr "" +msgstr "Der er i gang med at slette en anden brugers mediefil. Fortsæt med varsomhed." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." -msgstr "" +msgstr "Du slettede elementet fra samlingen." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." -msgstr "" +msgstr "Elementet blev ikke fjernet, fordi du ikke markerede at du var sikker." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." -msgstr "" +msgstr "Du er i færd med at slette et element fra en anden brugers samling. Fortsæt med varsomhed." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" -msgstr "" +msgstr "Du slettede samlingen \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." -msgstr "" +msgstr "Samlingen blev ikke slettet, fordi du undlod at angive at du var sikker." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." -msgstr "" +msgstr "Du er i færd med at slette en anden brugers samling. Fortsæt med varsomhed." diff --git a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo Binary files differindex 5ae794fa..5aee44a7 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 b3d82ee9..e1202161 100644 --- a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po @@ -3,27 +3,27 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <benjamin@lebsanft.org>, 2011. -# <cwebber@dustycloud.org>, 2011. -# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2011-2012. -# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2013. -# <jakob.kramer@gmx.de>, 2011, 2012. -# Jakob Kramer <jakob.kramer@gmx.de>, 2012-2013. -# Jan-Christoph Borchardt <JanCBorchardt@fsfe.org>, 2011. -# Jan-Christoph Borchardt <jan@unhosted.org>, 2011, 2012. -# <kyoo@kyoo.ch>, 2011. -# <mediagoblin.org@samba-tng.org>, 2011. -# Rafael Maguiña <rafael.maguina@gmail.com>, 2011. -# <sebastian@sspaeth.de>, 2012. -# Vinzenz Vietzke <vietzke@b1-systems.de>, 2012. -# Vinzenz Vietzke <vinz@fedoraproject.org>, 2011. +# piratenpanda <benjamin@lebsanft.org>, 2011 +# cwebber <cwebber@dustycloud.org>, 2011 +# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2011-2012 +# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2013 +# Jakob Kramer <jakob.kramer@gmx.de>, 2011, 2012 +# Jakob Kramer <jakob.kramer@gmx.de>, 2012-2013 +# Jan-Christoph Borchardt <hey@jancborchardt.net>, 2011 +# Jan-Christoph Borchardt <hey@jancborchardt.net>, 2011, 2012 +# Keyzo <kyoo@kyoo.ch>, 2011 +# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2011 +# Art O. Pal <artopal@fastmail.fm>, 2011 +# spaetz <sebastian@sspaeth.de>, 2012 +# vinzv Vietzke <vinz@vinzv.de>, 2012 +# vinzv Vietzke <vinz@vinzv.de>, 2011 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-07 13:16+0000\n" -"Last-Translator: Elrond <elrond+mediagoblin.org@samba-tng.org>\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: German (http://www.transifex.com/projects/p/mediagoblin/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -32,253 +32,264 @@ msgstr "" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Benutzerregistrierung ist auf diesem Server leider deaktiviert." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "Ungültiger Benutzername oder E-Mail-Adresse." -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "Dieses Feld akzeptiert keine E-Mail-Adressen." -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "Dieses Feld benötigt eine E-Mail-Adresse." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Benutzername" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Passwort" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "E-Mail-Adresse" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Benutzername oder E-Mail-Adresse" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Benutzerregistrierung ist auf diesem Server leider deaktiviert." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Leider gibt es bereits einen Benutzer mit diesem Namen." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Leider gibt es bereits einen Benutzer mit dieser E-Mail-Adresse." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Dein GNU MediaGoblin Konto wurde hiermit aktiviert. Du kannst dich jetzt anmelden, dein Profil bearbeiten und Medien hochladen." -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Der Aktivierungsschlüssel oder die Nutzerkennung ist falsch." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Du musst angemeldet sein, damit wir wissen, wer die Email bekommt." -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Deine E-Mail-Adresse wurde bereits aktiviert." -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Aktivierungsmail wurde erneut versandt." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "Falls jemand mit dieser E-Mail-Adresse (Groß- und Kleinschreibung wird unterschieden!) registriert ist, wurde eine E-Mail mit Anleitungen verschickt, wie Du Dein Passwort ändern kannst." - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "Es konnte niemand mit diesem Benutzernamen gefunden werden." - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Es wurde eine E-Mail mit der Anleitung zur Änderung des Passwortes an Dich gesendet." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Die E-Mail zur Wiederherstellung des Passworts konnte nicht verschickt werden, weil dein Benutzername inaktiv oder deine E-Mail-Adresse noch nicht aktiviert wurde." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Du kannst dich jetzt mit deinem neuen Passwort anmelden." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titel" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Beschreibung des Werkes" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Die Texte lassen sich durch <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> formatieren." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Schlagwörter" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Kommaseparierte Schlagwörter" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Kurztitel" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "Bitte gib einen Kurztitel ein" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Der Titelteil der Medienadresse. Normalerweise muss hier nichts geändert werden." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Lizenz" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Biographie" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Webseite" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Diese Adresse ist fehlerhaft" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Altes Passwort" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Gib dein altes Passwort ein, um zu bestätigen, dass du dieses Konto besitzt." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Mir eine E-Mail schicken, wenn andere meine Medien kommentieren" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Neues Passwort" +msgid "Enable insite notifications about events." +msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "Bevorzugte Lizenz" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "Dies wird Deine Standardlizenz in den Upload-Forumularen sein." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Mir eine E-Mail schicken, wenn andere meine Medien kommentieren" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "Der Titel kann nicht leer sein" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Beschreibung dieser Sammlung" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "Der Titelteil dieser Sammlungsadresse. Du musst ihn normalerweise nicht ändern." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Altes Passwort" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Gib dein altes Passwort ein, um zu bestätigen, dass du dieses Konto besitzt." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Neues Passwort" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Passwort" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Diesen Kurztitel hast du bereits vergeben." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Du bearbeitest die Medien eines anderen Nutzers. Sei bitte vorsichtig." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "Sie haben den Anhang %s hinzugefügt!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "Du kannst nur dein eigenes Profil bearbeiten." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Du bearbeitest das Profil eines anderen Nutzers. Sei bitte vorsichtig." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Das Profil wurde aktualisiert" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Falsches Passwort" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Kontoeinstellungen gespeichert" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "Du musst die Löschung deines Kontos bestätigen." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Du hast bereits eine Sammlung mit Namen »%s«!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "Eine Sammlung mit diesem Kurztitel existiert bereits für diesen Benutzer." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Du bearbeitest die Sammlung eines anderen Benutzers. Sei vorsichtig." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Falsches Passwort" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Theme kann nicht verknüpft werden … Kein Theme gesetzt\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "Für dieses Theme gibt es kein asset-Verzeichnis\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "Trotzdem wurde eine alte Verknüpfung gefunden; sie wurde entfernt\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -286,15 +297,202 @@ msgid "" "domain." msgstr "Das CSRF cookie ist nicht vorhanden. Das liegt vermutlich an einem Cookie-Blocker oder ähnlichem.<br/>Bitte stelle sicher, dass Cookies von dieser Domäne erlaubt sind." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Entschuldigung, dieser Dateityp wird nicht unterstützt." -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Videokonvertierung fehlgeschlagen" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "hat dein Medium kommentiert" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Benutzername" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "E-Mail-Adresse" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Benutzername oder E-Mail-Adresse" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Benutzername oder E-Mail-Adresse" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Falls jemand mit dieser E-Mail-Adresse (Groß- und Kleinschreibung wird unterschieden!) registriert ist, wurde eine E-Mail mit Anleitungen verschickt, wie Du Dein Passwort ändern kannst." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Es konnte niemand mit diesem Benutzernamen gefunden werden." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Es wurde eine E-Mail mit der Anleitung zur Änderung des Passwortes an Dich gesendet." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Die E-Mail zur Wiederherstellung des Passworts konnte nicht verschickt werden, weil dein Benutzername inaktiv oder deine E-Mail-Adresse noch nicht aktiviert wurde." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Du kannst dich jetzt mit deinem neuen Passwort anmelden." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Dein neues Passwort" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Passwort setzen" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Hast du noch keines?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Registriere dich einfach hier!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Passwort wiederherstellen" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Anweisungen senden" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Passwort vergessen?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Aufnahmeort" @@ -304,6 +502,10 @@ msgstr "Aufnahmeort" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "In <a href=\"%(osm_url)s\">OpenStreetMap</a> öffnen" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Erlauben" @@ -358,101 +560,370 @@ msgstr "Die Weiterleitungs-URI für die Anwendung, dieses Feld\n ist msgid "This field is required for public clients" msgstr "Dieses Feld ist Pflicht für öffentliche Clients" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Client {0} wurde registriert!" #: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 msgid "OAuth client connections" -msgstr "" +msgstr "OAuth-Client-Verbindungen" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "Deine OAuth-Clients" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Hinzufügen" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Löschen" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Anmelden" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Anmeldevorgang fehlgeschlagen!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Die Datei stimmt nicht mit dem gewählten Medientyp überein." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Datei" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Du musst eine Datei angeben." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "JAAA! Geschafft!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "Sammlung »%s« hinzugefügt!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Bild eines gestressten Goblins" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Bitte bestätige Deine E-Mail-Adresse!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "abmelden" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Anmelden" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "<a href=\"%(user_url)s\">%(user_name)s</a>s Konto" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Kontoeinstellungen ändern" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Medienverarbeitung" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "Abmelden" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Medien hinzufügen" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Neues Album erstellen" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Neuste Medien" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Neues Nutzerkonto registrieren!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Registrieren" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Hallo %(username)s,\n\num deinNutzerkonto bei GNU MediaGoblin zu aktivieren, musst du folgende Adresse in deinem Webbrowser öffnen:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." msgstr "Läuft mit <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, einem <a href=\"http://gnu.org/\">GNU</a>-Projekt." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -460,147 +931,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Veröffentlicht unter der <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a> (<a href=\"%(source_link)s\">Quellcode</a>)." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "Bild eines gestressten Goblins" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "Entdecken" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Hallo du, willkommen auf dieser MediaGoblin-Seite!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 msgid "" "This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " "extraordinarily great piece of media hosting software." msgstr "Diese Webseite setzt <a href=\"http://mediagoblin.org\">MediaGoblin</a> ein, eine großartige Software für Medienhosting." -#: mediagoblin/templates/mediagoblin/root.html:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Melde Dich mit Deinem MediaGoblin-Konto an, um eigene Medien hinzuzufügen, andere zu kommentieren und vieles mehr." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "Hast du noch keinen? Das geht ganz einfach!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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\">Registriere dich auf dieser Seite</a> oder <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Installiere MediaGoblin auf deinem eigenen Server</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Neuste Medien" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Hier kann man den Status von zu verarbeitenden Medien in diesem MediaGoblin-Exemplar sehen." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Medien in Bearbeitung" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Keine Medien in Bearbeitung" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Die folgenden Uploads sind fehlgeschlagen:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Keine fehlgeschlagenen Einträge!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "Die letzten zehn erfolgreichen Uploads" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Noch keine verarbeiteten Einträge!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Dein neues Passwort" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Passwort setzen" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Passwort wiederherstellen" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Anweisungen senden" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" "\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Hallo %(username)s,\n\num dein GNU-MediaGoblin-Passwort zu ändern, öffne folgende URL\nin deinem Webbrowser:\n\n%(verification_url)s\n\nWenn du denkst, dass es sich hierbei um einen Fehler handelt,\nignoriere einfach diese E-Mail und bleib ein glücklicher Goblin!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Anmeldevorgang fehlgeschlagen!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Hast du noch keines?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Registriere dich einfach hier!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Passwort vergessen?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Neues Nutzerkonto registrieren!" - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Registrieren" +" >Create an account at this site</a>\n" +" or" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" "\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" -"\n" -"%(verification_url)s" -msgstr "Hallo %(username)s,\n\num deinNutzerkonto bei GNU MediaGoblin zu aktivieren, musst du folgende Adresse in deinem Webbrowser öffnen:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -614,13 +984,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Bearbeite Anhänge von %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Anhänge" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Anhang hinzufügen" @@ -637,12 +1007,18 @@ msgstr "Abbrechen" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Änderungen speichern" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -653,7 +1029,7 @@ msgid "Yes, really delete my account" msgstr "Ja, ich möchte mein Konto wirklich löschen" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Dauerhaft löschen" @@ -670,10 +1046,14 @@ msgstr "%(media_title)s bearbeiten" msgid "Changing %(username)s's account settings" msgstr "%(username)ss Kontoeinstellungen ändern" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "Mein Konto löschen" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -685,6 +1065,39 @@ msgstr "Bearbeite %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "%(username)ss Profil bearbeiten" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -695,8 +1108,8 @@ msgstr "Medien mit Schlagwort: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Download" @@ -719,7 +1132,8 @@ msgid "" msgstr "Hol dir auf <a href=\"http://getfirefox.com\">http://getfirefox.com</a> einen modernen Webbrowser, der dieses Audiostück abspielen kann!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Originaldatei" @@ -727,6 +1141,11 @@ msgstr "Originaldatei" msgid "WebM file (Vorbis codec)" msgstr "WebM-Datei (Vorbis-Codec)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Originaldatum" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -737,70 +1156,267 @@ msgstr "WebM-Datei (Vorbis-Codec)" msgid "Image for %(media_title)s" msgstr "Bild für %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF-Datei" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "Perspektive" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "Vorderseite" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "Modell herunterladen" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "Dateiformat" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "Objekthöhe" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "Entschuldige, dieses Video wird nicht funktionieren, weil dein Webbrowser kein HTML5-Video unterstützt." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "Hol dir auf <a href=\"http://getfirefox.com\">http://getfirefox.com</a> einen modernen Webbrowser, der dieses Video abspielen kann!" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "WebM-Datei (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Hier kann man den Status von zu verarbeitenden Medien in diesem MediaGoblin-Exemplar sehen." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Medien in Bearbeitung" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Keine Medien in Bearbeitung" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Die folgenden Uploads sind fehlgeschlagen:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Keine fehlgeschlagenen Einträge!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Die letzten zehn erfolgreichen Uploads" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Noch keine verarbeiteten Einträge!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Eine Sammlung hinzufügen" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Deine Medien" @@ -819,11 +1435,6 @@ msgstr "%(collection_title)s von <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "Bearbeiten" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Löschen" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -835,7 +1446,7 @@ msgstr "Möchtest du %(title)s wirklich löschen?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Wirklich »%(media_title)s« aus »%(collection_title)s« entfernen?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Entfernen" @@ -878,24 +1489,21 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>s Medien" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Medien von <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Einen Kommentar schreiben" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Kommentar absenden" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "um" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Veröffentlicht am</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Hinzugefügt" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -920,85 +1528,107 @@ msgstr "Du kannst hier den Status der Medien verfolgen, die sich gerade in Bearb msgid "Your last 10 successful uploads" msgstr "Deine zehn letzten erfolgreichen Uploads" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)ss Profil" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Dieser Benutzer konnte leider nicht gefunden werden." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "E-Mail Aktivierung benötigt" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Fast fertig! Dein Konto muss noch freigeschaltet werden." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Gleich solltest du eine E-Mail erhalten, die beschreibt was noch zu tun bleibt." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Falls sie nicht ankommt:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Aktivierungsmail erneut senden" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Jemand hat bereits ein Konto mit diesem Benutzernamen registriert, aber es muss noch aktiviert werden." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Wenn dir dieses Konto gehört und die Aktivierungsmail verloren gegangen ist, kannst du dich <a href=\"%(login_url)s\">anmelden</a> und sie erneut senden." +msgid "%(username)s's profile" +msgstr "%(username)ss Profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Hier kannst Du Dich selbst beschreiben." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Profil bearbeiten" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Dieser Benutzer hat (noch) keine Daten in seinem Profil." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "Sammlungen durchstöbern" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Alle Medien von %(username)s anschauen" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Hier erscheinen deine Medien, sobald du etwas hochgeladen hast." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Scheinbar gibt es hier noch nichts …" +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "E-Mail Aktivierung benötigt" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Fast fertig! Dein Konto muss noch freigeschaltet werden." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Gleich solltest du eine E-Mail erhalten, die beschreibt was noch zu tun bleibt." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Falls sie nicht ankommt:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Aktivierungsmail erneut senden" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Jemand hat bereits ein Konto mit diesem Benutzernamen registriert, aber es muss noch aktiviert werden." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Wenn dir dieses Konto gehört und die Aktivierungsmail verloren gegangen ist, kannst du dich <a href=\"%(login_url)s\">anmelden</a> und sie erneut senden." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "(entfernen)" @@ -1047,50 +1677,85 @@ msgstr "neuer" msgid "older" msgstr "älter" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Schlagwörter" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Die Bilddatei konnte nicht gelesen werden." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Hoppla!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Ein Fehler trat auf" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "Funktion nicht erlaubt" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "So nicht!</p><p>Du wolltest eine Funktion verwenden zu der Du nicht die nötigen Rechte Rechte besitzt. Wolltest Du etwa schon wieder alle Nutzerkonten löschen?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "Tut uns Leid, aber unter der angegebenen Adresse gibt es keine Seite!</p><p>Wenn du sicher bist, dass die Adresse stimmt, wurde die Seite eventuell verschoben oder gelöscht." +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "Jahr" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "Monat" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "Woche" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "Tag" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "Stunde" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "Minute" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "Kommentar" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Die Texte lassen sich durch <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> formatieren." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1112,73 +1777,84 @@ msgstr "-- Auswählen --" msgid "Include a note" msgstr "Notiz anfügen" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "hat dein Medium kommentiert" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Hoppla, der Kommentartext fehlte." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Dein Kommentar wurde angenommen!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "Bitte prüfe deinen Einträge und versuche erneut." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Du musst eine Sammlung auswählen oder hinzufügen" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "»%s« ist bereits in der Sammlung »%s«" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "»%s« zur Sammlung »%s« hinzugefügt" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Du hast das Medium gelöscht." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "Das Medium wurde nicht gelöscht, da nicht angekreuzt hast, dass du es wirklich löschen möchtest." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Du versuchst Medien eines anderen Nutzers zu löschen. Sei bitte vorsichtig." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Du hast das Objekt aus der Sammlung gelöscht." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "Das Objekt wurde nicht aus der Sammlung entfernt, weil du nicht bestätigt hast, dass du dir sicher bist." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Du bist dabei ein Objekt aus der Sammlung eines anderen Nutzers zu entfernen. Sei vorsichtig." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Du hast die Sammlung »%s« gelöscht" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "Die Sammlung wurde nicht gelöscht, weil du nicht bestätigt hast, dass du dir sicher bist." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Du bist dabei eine Sammlung eines anderen Nutzers zu entfernen. Sei vorsichtig." diff --git a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po index 6950f515..0d418eb9 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: 2013-03-11 17:21-0500\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,105 +17,78 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" - -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:60 -msgid "Email address" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." msgstr "" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." msgstr "" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "" -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your " "profile, and submit images!" msgstr "" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been " -"sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or " -"your account's email address has not been verified." -msgstr "" - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a " @@ -123,147 +96,186 @@ msgid "" " Markdown</a> for formatting." msgstr "" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie " @@ -271,15 +283,201 @@ msgid "" "this domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:37 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been " +"sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or " +"your account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "" @@ -289,6 +487,10 @@ msgstr "" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -347,7 +549,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -360,218 +562,327 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 -msgid "Invalid file given for media type." +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." msgstr "" -#: mediagoblin/submit/forms.py:26 -msgid "File" +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" msgstr "" -#: mediagoblin/submit/views.py:51 -msgid "You must provide a file." +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" msgstr "" -#: mediagoblin/submit/views.py:97 -msgid "Woohoo! Submitted!" +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/plugins/openid/views.py:106 #, python-format -msgid "Collection \"%s\" added!" +msgid "Verification of %s failed: %s" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 -msgid "Verify your email!" +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 -msgid "log out" +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 #: mediagoblin/templates/mediagoblin/auth/login.html:28 #: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 msgid "Log in" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:79 -#, python-format -msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 -msgid "Change account settings" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 -msgid "Media processing panel" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 -msgid "Add media" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 -#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 -msgid "Create new collection" +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> " -"project." +"You can't delete your only Persona email address unless you have a " +"password set." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "" + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "" + +#: mediagoblin/submit/forms.py:41 msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a" -" href=\"%(source_link)s\">Source code</a> available." +"You can use\n" +" <a " +"href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." msgstr "" +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "" + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, " -"an extraordinarily great piece of media hosting software." +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your" -" MediaGoblin account." +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an " -"account at this site</a>\n" -" or\n" -" <a class=\"button_action\" " -"href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on " -"your own server</a>" +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 @@ -579,7 +890,7 @@ msgstr "" msgid "Create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "" @@ -594,6 +905,65 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> " +"project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a" +" href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, " +"an extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your" +" MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" " +"href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your " +"own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -606,13 +976,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -629,12 +999,18 @@ msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -645,7 +1021,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "" @@ -662,10 +1038,14 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -677,6 +1057,41 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then" +" \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can " +"ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -687,8 +1102,8 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "" @@ -711,7 +1126,8 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -719,6 +1135,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -729,70 +1150,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them." +"\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "" @@ -811,11 +1429,6 @@ msgstr "" msgid "Edit" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -827,7 +1440,7 @@ msgstr "" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -871,23 +1484,20 @@ msgstr "" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -912,84 +1522,106 @@ msgstr "" msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 -msgid "An email should arrive in a few moments with instructions on how to do so." -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to" -" be activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can " -"<a href=\"%(login_url)s\">log in</a> and resend it." +msgid "%(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "" +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "An email should arrive in a few moments with instructions on how to do so." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to" +" be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can " +"<a href=\"%(login_url)s\">log in</a> and resend it." +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1038,40 +1670,76 @@ msgstr "" msgid "older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're " "sure the address is correct, maybe the page you're looking for has been " "moved or deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" @@ -1079,8 +1747,8 @@ msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" "You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> " -"for formatting." +"href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1103,74 +1771,87 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a " +"href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed " "with caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were " "sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo Binary files differindex ac74a68b..4a4a1cf4 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 e7785d73..bb6aef38 100644 --- a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po @@ -3,18 +3,18 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <deletesoftware@yandex.ru>, 2013. -# <deletesoftware@yandex.ru>, 2011-2012. -# Fernando Inocencio <faigos@gmail.com>, 2011. -# <john_w1954@fastmail.fm>, 2011. +# aleksejrs <deletesoftware@yandex.ru>, 2013 +# aleksejrs <deletesoftware@yandex.ru>, 2011-2012 +# Fernando Inocencio <faigos@gmail.com>, 2011 +# tiguliano <john_w1954@fastmail.fm>, 2011 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-10 16:50+0000\n" -"Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"Language-Team: Esperanto (http://www.transifex.com/projects/p/mediagoblin/language/eo/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -22,253 +22,264 @@ msgstr "" "Language: eo\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "BedaÅrinde, registrado estas malaktivigita en tiu ĉi instalaĵo." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "Nevalida ensalutnomo aÅ retpoÅtadreso." -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "Ĉi tiu kampo ne akceptas retpoÅtadresojn." -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "Ĉi tiu kampo postulas retpoÅtadreson." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Uzantnomo" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Pasvorto" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "RetpoÅtadreso" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Salutnomo aÅ retpoÅtadreso" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "BedaÅrinde, registrado estas malaktivigita en tiu ĉi instalaĵo." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "BedaÅrinde, uzanto kun tiu nomo jam ekzistas." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Ni bedaÅras, sed konto kun tiu retpoÅtadreso jam ekzistas." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Via retpoÅtadreso estas konfirmita. Vi povas nun ensaluti, redakti vian profilon, kaj alÅuti bildojn!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "La kontrol-kodo aÅ la uzantonomo ne estas korekta" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Vi devas esti ensalutita, por ke ni sciu, al kiu sendi la retleteron!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Vi jam konfirmis vian retpoÅtadreson!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Resendi vian kontrol-mesaÄon." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "Se tiu retpoÅtadreso (majuskloj gravas!) estas registrita, tien senditas retletero kun instrukcio pri kiel ÅanÄi vian pasvorton." - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "Trovitas neniu kun tiu ensalutnomo." - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Senditas retletero kun instrukcio pri kiel ÅanÄi vian pasvorton." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Ni ne povas sendi pasvortsavan retleteron, ĉar aÅ via konto estas neaktiva, aÅ Äia retpoÅtadreso ne estis konfirmita." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Nun vi povas ensaluti per via nova pasvorto." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titolo" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Priskribo de ĉi tiu verko" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Vi povas uzi por markado la lingvon\n «<a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a>»." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Etikedoj" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Dividu la etikedojn per komoj." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "La distingiga adresparto" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "La distingiga adresparto ne povas esti malplena" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "La dosiertitol-bazita parto de la dosieradreso. Ordinare ne necesas Äin ÅanÄi." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Permesilo" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Retejo" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Ĉi tiu adreso enhavas erarojn" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "La malnova pasvorto" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Enigu vian malnovan pasvorton por pruvi, ke ĉi tiu konto estas via." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "RetpoÅtu min kiam aliaj komentas pri miaj alÅutaĵoj." #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "La nova pasvorto" +msgid "Enable insite notifications about events." +msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "Permesila prefero" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" - -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "RetpoÅtu min kiam aliaj komentas pri miaj alÅutaĵoj." +msgstr "Tiu ĉi permesilo estos antaÅelektita en la alÅutformularoj." -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "La titolo ne povas malpleni." -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Priskribo de la kolekto" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "La distingiga adresparto de ĉi tiu kolekto. Ordinare ne necesas Äin ÅanÄi." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "La malnova pasvorto" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Enigu vian malnovan pasvorton por pruvi, ke ĉi tiu konto estas via." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "La nova pasvorto" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Pasvorto" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Ĉi tiu uzanto jam havas dosieron kun tiu distingiga adresparto." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Vi priredaktas dosieron de alia uzanto. Agu singardeme." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "Vi aldonis la kundosieron %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "Vi povas redakti nur vian propran profilon." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Vi redaktas profilon de alia uzanto. Agu singardeme." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "ProfilÅanÄoj estis konservitaj" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "MalÄusta pasvorto" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Kontagordoj estis konservitaj" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "Vi bezonas konfirmi la forigon de via konto." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Vi jam havas kolekton kun la nomo «%s»!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "Ĉi tiu uzanto jam havas kolekton kun tiu distingiga adresparto." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Vi redaktas kolekton de alia uzanto. Agu singardeme." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "MalÄusta pasvorto" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Alligo de etoso ne eblas… ne estas elektita ekzistanta etoso\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "Mankas dosierujo kun aspektiloj por la etoso\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "Tamen trovitas — kaj forigitas — malnova simbola ligilo al dosierujo.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -276,15 +287,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Mi pardonpetas, mi ne subtenas tiun dosiertipon :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Malsukcesis transkodado de filmo" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "komentis je via afiÅo" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Uzantnomo" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "RetpoÅtadreso" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Uzantonomo aÅ retpoÅtadreso" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Salutnomo aÅ retpoÅtadreso" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Se tiu retpoÅtadreso (majuskloj gravas!) estas registrita, tien senditas retletero kun instrukcio pri kiel ÅanÄi vian pasvorton." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Trovitas neniu kun tiu ensalutnomo." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Senditas retletero kun instrukcio pri kiel ÅanÄi vian pasvorton." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Ni ne povas sendi pasvortsavan retleteron, ĉar aÅ via konto estas neaktiva, aÅ Äia retpoÅtadreso ne estis konfirmita." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Nun vi povas ensaluti per via nova pasvorto." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Via pasvorto estas sukcese ÅanÄita" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Enigu vian novan pasvorton" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Difini pasvorton" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "ÅœanÄado de pasvorto de %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Konservi" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Ĉu ankoraÅ sen konto?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Kreu Äin ĉi tie!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Ekhavo de nova pasvorto" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Sendi instrukcion" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Ĉu vi forgesis vian pasvorton?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Loko" @@ -294,6 +492,10 @@ msgstr "Loko" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Vidi sur <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -348,7 +550,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -361,88 +563,357 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Aldoni" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Forigi" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Ensaluti" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Ensaluto malsukcesis!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "La provizita dosiero ne konformas al la informtipo." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Dosiero" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Vi devas provizi dosieron." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Hura! AlÅutitas!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "Kolekto «%s» aldonitas!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Bildo de zorgigita koboldo" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Konfirmu viecon de la retpoÅtadreso!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "elsaluti" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Ensaluti" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "Konto de <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "ÅœanÄi kontagordojn" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Kontrolejo pri dosierpreparado." -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "Elsaluti" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Aldoni dosieron" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Krei novan kolekton" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Laste aldonitaj dosieroj" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Kreu konton!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Krei" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Sal %(username)s,\n\npor aktivigi vian GNU MediaGoblin konton, malfermu la sekvantan URLon en via retumilo:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." msgstr "Funkcias per <a href=\"http://mediagoblin.org/\" title='Versio %(version)s'>MediaGoblin</a>, unu el la <a href=\"http://gnu.org/\">projektoj de GNU</a>." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -450,147 +921,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Disponigita laÅ la permesilo <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. Haveblas<a href=\"%(source_link)s\">fontotekstaro</a>." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "Bildo de zorgigita koboldo" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "ĈirkaÅrigardi" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Saluton, kaj bonvenon al ĉi tiu MediaGoblina retpaÄaro!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 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:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Por aldoni viajn proprajn dosierojn, afiÅi komentariojn ktp, vi povas ensaluti je via MediaGoblina konto." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "Ĉu vi ankoraÅ ne havas tian? Ne malÄoju!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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:47 -msgid "Most recent media" -msgstr "Laste aldonitaj dosieroj" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Ĉi tie vi povas observi la staton de prilaborado de alÅutaĵoj en ĉi tiu servilo." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Dosieroj preparataj" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Neniu dosieroj preparatas" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Preparado de ĉi tiuj alÅutaĵoj malsukcesis:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Ne ekzistas malsukcesaj eroj!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "La dek lastaj sukcesaj alÅutoj" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "AnkoraÅ ne ekzistas eroj prilaboritaj!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Enigu vian novan pasvorton" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Difini pasvorton" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Ekhavo de nova pasvorto" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Sendi instrukcion" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" "\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Saluton, %(username)s,\n\npor ÅanÄi vian pasvorton ĉe GNUa MediaGoblin, sekvu la jenan retadreson per via TTT-legilo:\n\n%(verification_url)s\n\nSe vi pensas, ke ĉi tiu retletero estas sendita erare, simple ignoru Äin kaj plu restu feliĉa koboldo!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Ensaluto malsukcesis!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Ĉu ankoraÅ sen konto?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Kreu Äin ĉi tie!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Ĉu vi forgesis vian pasvorton?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Kreu konton!" - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Krei" +" >Create an account at this site</a>\n" +" or" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" -"\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" "\n" -"%(verification_url)s" -msgstr "Sal %(username)s,\n\npor aktivigi vian GNU MediaGoblin konton, malfermu la sekvantan URLon en via retumilo:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -604,13 +974,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Aldoni kundosierojn por %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Kundosieroj" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Aldoni kundosieron" @@ -627,12 +997,18 @@ msgstr "Nuligi" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Konservi ÅanÄojn" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -643,7 +1019,7 @@ msgid "Yes, really delete my account" msgstr "Jes, efektive forigi mian konton" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Forigi senrevene" @@ -660,10 +1036,14 @@ msgstr "Priredaktado de %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "ÅœanÄado de kontagordoj de %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "Forigi mian konton." +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -675,6 +1055,39 @@ msgstr "Redaktado de %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Redaktado de l’profilo de %(username)s'" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "antaÅ %(formatted_time)s" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -685,8 +1098,8 @@ msgstr "Dosieroj kun etikedo: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "ElÅuti" @@ -709,7 +1122,8 @@ msgid "" msgstr "Vi povas akiri modernan TTT-legilon, kapablan \n\tsonigi la registraĵon ĉe <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "originalan dosieron" @@ -717,6 +1131,11 @@ msgstr "originalan dosieron" msgid "WebM file (Vorbis codec)" msgstr "WebMan dosieron (kun Vorbisa kodaĵo)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Kreita" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -727,70 +1146,267 @@ msgstr "WebMan dosieron (kun Vorbisa kodaĵo)" msgid "Image for %(media_title)s" msgstr "Bildo de «%(media_title)s»" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF-dosiero" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "DeantaÅe" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "Desupre" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "Deflanke" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "ElÅuti la modelon" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "InformaranÄo" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "Alto de la objekto" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "BedaÅrinde, ĉi tiu filmo ne montriÄos\n ĉar via TTT-legilo ne subtenas sufiĉe\n filmojn laÅ HTML5." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "Vi povas elÅuti modernan TTT-legilon, kapablan \n montri la filmon, de <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "la WebM-dosieron (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Ĉi tie vi povas observi la staton de prilaborado de alÅutaĵoj en ĉi tiu servilo." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Dosieroj preparataj" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Neniu dosieroj preparatas" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Preparado de ĉi tiuj alÅutaĵoj malsukcesis:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Ne ekzistas malsukcesaj eroj!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "La dek lastaj sukcesaj alÅutoj" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "AnkoraÅ ne ekzistas eroj prilaboritaj!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Aldonado de kolekto" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Aldono de via dosiero" @@ -809,11 +1425,6 @@ msgstr "%(collection_title)s de <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "ÅœanÄi" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Forigi" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -825,7 +1436,7 @@ msgstr "Ĉu vere forigi %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Ĉu vere forigi %(media_title)s el %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Forigi" @@ -868,24 +1479,21 @@ msgstr "Dosieroj de <a href=\"%(user_url)s\">%(username)s</a>" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "■ПроÑмотр файлов Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Aldoni komenton" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Aldoni ĉi tiun komenton" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "je" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Aldonita je</h3>\n <p>la %(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Aldonita" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -910,85 +1518,107 @@ msgstr "Ĉi tie vi povas informiÄi pri la stato de preparado de dosieroj por vi msgid "Your last 10 successful uploads" msgstr "Viaj 10 lastaj sukcesaj alÅutoj." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Profilo de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Uzanto ne trovita." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Necesas konfirmo de retpoÅtadreso" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "PreskaÅ finite! Restas nur validigi vian konton." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Post kelkaj momentoj devas veni retletero kun instrukcio pri kiel tion fari." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Se tio ne okazas:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Resendi kontrolmesaÄon" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Iu registris konton kun tiu ĉi uzantonomo, sed Äi devas ankoraÅ esti aktivigita." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Se vi estas tiu sed vi perdis vian kontrolmesaÄon, vi povas <a href=\"%(login_url)s\">ensaluti</a> kaj resendi Äin." +msgid "%(username)s's profile" +msgstr "Profilo de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Jen estas spaceto por rakonti pri vi al aliaj." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Redakti profilon" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Ĉi tiu uzanto ne jam aldonis informojn pri si." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "Vidi kolektojn" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Rigardi ĉiujn dosierojn de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Äœuste ĉi tie aperos viaj dosieroj, sed vi Åajne ankoraÅ nenion alÅutis." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Ĉi tie Åajne estas ankoraÅ neniuj dosieroj…" +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Necesas konfirmo de retpoÅtadreso" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "PreskaÅ finite! Restas nur validigi vian konton." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Post kelkaj momentoj devas veni retletero kun instrukcio pri kiel tion fari." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Se tio ne okazas:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Resendi kontrolmesaÄon" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Iu registris konton kun tiu ĉi uzantonomo, sed Äi devas ankoraÅ esti aktivigita." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Se vi estas tiu sed vi perdis vian kontrolmesaÄon, vi povas <a href=\"%(login_url)s\">ensaluti</a> kaj resendi Äin." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "(forigi)" @@ -1037,50 +1667,85 @@ msgstr "pli nova" msgid "older" msgstr "malpli nova" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Markita per" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Malsukcesis lego de la bildodosiero" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Oj!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Okazis eraro" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "jaro(j)" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "monato(j)" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "semajno(j)" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "tago(j)" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "horo(j)" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minuto(j)" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "Komenti" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Vi povas uzi por markado la lingvon «<a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a>»." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1102,73 +1767,84 @@ msgstr "-- Elektu --" msgid "Include a note" msgstr "Rimarko" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "komentis je via afiÅo" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Ve, komentado estas malebligita." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Oj, via komento estis malplena." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Via komento estis afiÅita!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "Bonvolu kontroli vian enigitaĵon kaj reprovi." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Necesas elekti aÅ aldoni kolekton" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "«%s» jam estas en la kolekto «%s»" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "«%s» estis aldonita al la kolekto «%s»" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Vi forigis la dosieron." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 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:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Vi estas forigonta dosieron de alia uzanto. Estu singardema." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Vi forigis la dosieron el la kolekto." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed 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:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Vi estas forigonta dosieron el kolekto de alia uzanto. Agu singardeme." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Vi forigis la kolekton «%s»" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "La kolekto ne estis forigita, ĉar vi ne konfirmis vian certecon per la markilo." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Vi estas forigonta kolekton de alia uzanto. Agu singardeme." diff --git a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo Binary files differindex e2df0731..7ae0d7e3 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 21dce0b1..5f77bf0f 100644 --- a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po @@ -3,24 +3,25 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <deletesoftware@yandex.ru>, 2011, 2012. -# <ekenbrand@hotmail.com>, 2011. -# <jacobo@gnu.org>, 2011-2012. -# Javier Di Mauro <javierdimauro@gmail.com>, 2011. -# <juangsub@gmail.com>, 2011. -# <juanma@kde.org.ar>, 2011, 2012. -# <larjona99@gmail.com>, 2012. -# Laura Arjona Reina <larjona99@gmail.com>, 2013. -# Mario Rodriguez <msrodriguez00@gmail.com>, 2011. -# <mu@member.fsf.org>, 2011. -# <shackra@riseup.net>, 2012. -# <stardustprincess17@hotmail.com>, 2012. +# aleksejrs <deletesoftware@yandex.ru>, 2011, 2012 +# ekenbrand <ekenbrand@hotmail.com>, 2011 +# nvjacobo <jacobo@gnu.org>, 2011-2012 +# nvjacobo <jacobo@gnu.org>, 2013 +# Javier Di Mauro <javierdimauro@gmail.com>, 2011 +# case <juangsub@gmail.com>, 2011 +# juanman <juanma@kde.org.ar>, 2011, 2012 +# larjona <larjona99@gmail.com>, 2012 +# larjona <larjona99@gmail.com>, 2013 +# Mario Rodriguez <msrodriguez00@gmail.com>, 2011 +# Manuel Urbano Santos <mu@member.fsf.org>, 2011 +# shackra <shackra@riseup.net>, 2012 +# Elesa <stardustprincess17@hotmail.com>, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: Spanish (http://www.transifex.com/projects/p/mediagoblin/language/es/)\n" "MIME-Version: 1.0\n" @@ -30,253 +31,264 @@ msgstr "" "Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Lo sentimos, el registro está deshabilitado en este momento." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "Lo siento, el envÃo de informes está deshabilitado en esta instancia." + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "Lo siento, la autenticación está deshabilitada en esta instancia." + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "Nombre de usuario o correo electrónico inválido." -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "Este campo no acepta direcciones de correo." -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "Este campo requiere una dirección de correo." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Nombre de usuario" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Contraseña" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Dirección de correo electrónico" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Nombre de usuario o email" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Lo sentimos, el registro está deshabilitado en este momento." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Lo sentimos, ya existe un usuario con ese nombre." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Lo sentimos, ya existe un usuario con esa dirección de email." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "La clave de verificación o el identificador de usuario son incorrectos." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Tu dirección de correo electrónico ha sido verificada. ¡Ahora puedes iniciar sesión, editar tu perfil, y enviar imágenes!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "La clave de verificación o la identificación de usuario son incorrectas" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 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:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "¡Ya has verificado tu dirección de correo!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Se reenvió tu correo electrónico de verificación." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "Si esa dirección de correo (¡sensible a mayúsculas y minúsculas!) está registrada, se ha enviado un correo con instrucciones para cambiar la contraseña." - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "No se ha podido encontrar a nadie con ese nombre de usuario." - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Un correo electrónico ha sido enviado con instrucciones sobre cómo cambiar tu contraseña." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "No se pudo enviar un correo electrónico de recuperación de contraseñas porque tu nombre de usuario está inactivo o la dirección de su cuenta de correo electrónico no ha sido verificada." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Ahora tu puedes iniciar sesión usando tu nueva contraseña." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "TÃtulo" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Descripción de esta obra" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Puedes usar\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> para el formato." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Etiquetas" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Separa las etiquetas por comas." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Ficha" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "La ficha no puede estar vacÃa" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "El tÃtulo de esta parte de la dirección de los contenidos. Por lo general no es necesario cambiar esto." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Licencia" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Sitio web" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "La dirección contiene errores" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Vieja contraseña" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Escriba la anterior contraseña para demostrar que esta cuenta te pertenece." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "EnvÃame un correo cuando otros escriban comentarios sobre mi contenido" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nueva contraseña" +msgid "Enable insite notifications about events." +msgstr "Habilitar dentro del sitio notificaciones sobre eventos." -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "Preferencias de licencia" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "Ésta será tu licencia predeterminada en los formularios de subida." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "EnvÃame un correo cuando otros escriban comentarios sobre mi contenido" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "El tÃtulo no puede estar vacÃo" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Descripción de esta colección" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "El tÃtulo de la dirección de esta colección. Generalmente no necesitas cambiar esto." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Vieja contraseña" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Escriba la anterior contraseña para demostrar que esta cuenta te pertenece." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nueva contraseña" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Nueva dirección de correo electrónico" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Contraseña" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Introduce tu contraseña para probar que posees la cuenta." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Una entrada con esa ficha ya existe para este usuario." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Estás editando el contenido de otro usuario. Procede con precaución." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "¡Has añadido el adjunto %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "Sólo puedes editar tu propio perfil." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Estás editando un perfil de usuario. Procede con precaución." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Los cambios de perfil fueron salvados" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Contraseña incorrecta" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "las configuraciones de cuenta fueron salvadas" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "Necesitas confirmar el borrado de tu cuenta." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "¡Ya tienes una colección llamada \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "Una colección con esa ficha ya existe para este usuario/a." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Estás editando la colección de otro usuario/a. Ten cuidado." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Tu dirección de correo electrónico ha sido verificada." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Contraseña incorrecta" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "No se puede enlazar al tema... no hay un tema seleccionado\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "No hay directorio activo para este tema\n\n\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "Sin embargo, se encontró un enlace simbólico de un directorio antiguo; ha sido borrado.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "No se pudo enlazar \"%s\": %s existe y no es un enlace simbólico\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "Omitiendo \"%s\"; ya está establecido.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "Se encontró un enlace antiguo para \"%s\"; se eliminará.\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -284,15 +296,202 @@ msgid "" "domain." msgstr "No se encuentra la cookie CSRF. Esto suele ser debido a un bloqueador de cookies o similar.<br/> Por favor asegúrate de permitir las cookies para este dominio." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Lo sentidos, No soportamos ese tipo de archivo :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "ha fallado la ejecución de unoconv, comprueba el fichero de registro (log)" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Ha fallado la conversión de vÃdeo" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "Retirar el privilegio" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "Inhabilitar el usuario" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "Enviar un mensaje al usuario" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "Borrar el contenido" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "El usuario estará inhabilitado hasta:" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "¿Por qué estás inhabilitando este usuario?" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "¿Qué acción tomarás para resolver el informe?" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "¿Qué privilegios vas a retirar?" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "Advertencia de" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "comentó tu publicación" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "¡Suscrito a comentarios sobre %s!" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "No recibirás notificaciones de comentarios sobre %s." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "Se debe proporcionar un código (token) de OAuth." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "No se ha encontrado el código (token) de petición." + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "Lo siento, el archivo es demasiado grande." + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "Lo siento, subir este archivo sobrepasarÃa tu lÃmite de subida." + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "Lo siento, has alcanzado tu lÃmite de subida." + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Nombre de usuario" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Dirección de correo electrónico" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Nombre de usuario o correo electrónico" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "Mantener iniciada la sesión" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Nombre de usuario o email" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Si esa dirección de correo (¡sensible a mayúsculas y minúsculas!) está registrada, se ha enviado un correo con instrucciones para cambiar la contraseña." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "No se ha podido encontrar a nadie con ese nombre de usuario." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Un correo electrónico ha sido enviado con instrucciones sobre cómo cambiar tu contraseña." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "No se pudo enviar un correo electrónico de recuperación de contraseñas porque tu nombre de usuario está inactivo o la dirección de su cuenta de correo electrónico no ha sido verificada." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "El identificador de usuario es incorrecto." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Ahora tu puedes iniciar sesión usando tu nueva contraseña." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "Ya no eres un usuario activo. Por favor contacta con el administrador del sistema para reactivar tu cuenta." + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Se ha cambiado la contraseña correctamente" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Coloca tu nueva contraseña " + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Coloca la contraseña" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Cambiando la contraseña de %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Guardar" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "¿No tienes una cuenta?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "¡Crea una aquÃ!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "Cambiar tu contraseña." + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Recuperar contraseña" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Enviar instrucciones" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "¿Olvidaste tu contraseña?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Locación" @@ -302,6 +501,10 @@ msgstr "Locación" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Ver en <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "¡Inicia sesión para crear una cuenta!" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Permitir" @@ -356,7 +559,7 @@ msgstr "La URI para redireccionar las aplicaciones, este campo es <strong>requer msgid "This field is required for public clients" msgstr "Este campo es requerido para los clientes públicos" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "¡El cliente {0} ha sido registrado!" @@ -369,88 +572,357 @@ msgid "Your OAuth clients" msgstr "Tus clientes OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Añadir " -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "Lo siento, ya hay registrada una cuenta con esa OpenID." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "Lo siento, no se ha encontrado el servidor OpenID" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "No se ha encontrado el servicio OpenID para %s" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Falló la verificación de %s: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Verificación cancelada" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "Tu url de OpenID se ha guardado correctamente." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "No puedes borrar tu única url de OpenID a menos que tengas establecida una contraseña" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "Esa OpenID no está registrada para esta cuenta." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "Se ha eliminado correctamente la OpenID." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Agregar una OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Eliminar una OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Borrar" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "OpenID's" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Iniciar sesión" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "¡Hubo un fallo al iniciar sesión!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "¡Inicia sesión para crear una cuenta!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "¡O inicia sesión con contraseña!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "¡O inicia sesión con OpenID!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "¡O regÃstrate con OpenID!" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "Lo siento, ya hay una cuenta registrada para ese correo electrónico de Persona." + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "La dirección de correo electrónico de Persona se ha eliminado correctamente." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "No puedes borrar tu única dirección de correo electrónico de Persona a menos que tengas establecida una contraseña." + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "Esa dirección de correo electrónico de Persona no está registrada para esta cuenta." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "Lo siento, ya hay una cuenta registrada con esa dirección de correo electrónico de Persona." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Se ha guardado correctamente tu dirección de correo electrónico de Persona." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "Eliminar una dirección de correo electrónico de Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "Agregar una dirección de correo electrónico de Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "De Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "¡O inicia sesión con Persona!" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "¡O regÃstrate con Persona!" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Archivo inválido para el formato seleccionado." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "La copia al almacenamiento público ha fallado." + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "No se ha encontrado un fichero de procesamiento aceptable" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "Tamaño máximo de archivo: {0} mb" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Archivo" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "Puedes usarâŽ\n<a href=\"http://daringfireball.net/projects/markdown/basics\">âŽ\nMarkdown</a> para dar formato." + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Debes proporcionar un archivo." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "¡Yuju! ¡Enviado!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "¡Colección \"%s\" añadida!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "Estás inhabilitado." + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Imagen de un goblin estresándose" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "Has sido inhabilitado" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "hasta el %(until_when)s" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "indefinidamente" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "¡Verifica tu email!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "cerrar sesión" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Iniciar sesión" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "Cuenta de <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Cambiar la configuración de la cuenta" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Panel de procesamiento de contenido" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "Cerrar sesión" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Añadir contenido" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Crear nueva colección" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "Panel de gestión de usuarios" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "Panel de gestión de informes" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "El contenido más reciente" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Autorización" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "Autorizar" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Has iniciado sesión como" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "¿Quieres autorizar a" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "una aplicación desconocida" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "para que acceda a tu cuenta?" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Las aplicaciones con acceso a tu cuenta pueden:" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "Publicar nuevos contenidos por tÃ" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "Ver tu información (p.ej. perfil, contenidos, etc...)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "Cambiar tu información" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "Autorización finalizada" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "Autorización completa" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Copia y pega esto en tu cliente:" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "¡Crea una cuenta!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Crear" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Hola %(username)s,\n\npara activar tu cuenta de GNU MediaGoblin, abre la siguiente URL en tu navegador:\n\n%(verification_url)s " + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." msgstr "Funciona con <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, un proyecto <a href=\"http://gnu.org/\">GNU</a>." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -458,147 +930,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Publicado bajo la <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\"> Código fuente</a> disponible." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "Imagen de un goblin estresándose" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "Términos del Servicio" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "Explorar" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Hola, ¡bienvenido a este sitio de MediaGoblin!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 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 extraordinario programa libre para alojar, gestionar y compartir contenido multimedia." -#: mediagoblin/templates/mediagoblin/root.html:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Para añadir tus propios contenidos, dejar comentarios y más, puedes iniciar sesión con tu cuenta de MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "¿Aún no tienes una? ¡Es fácil!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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:47 -msgid "Most recent media" -msgstr "El contenido más reciente" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Aquà puedes llevar un seguimiento del estado del contenido que se está procesando en esta instancia." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Procesando contenido" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "No hay contenidos en procesamiento" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Estos archivos no pudieron ser procesados:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "¡No han fallado entradas!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "Últimos 10 envÃos con éxito" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "¡Aún no hay entradas procesadas!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Coloca tu nueva contraseña " - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Coloca la contraseña" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Recuperar contraseña" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Enviar instrucciones" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" "\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Hola %(username)s,\n\nPara cambiar tu contraseña de GNU MediaGoblin, abre la siguiente URL en un navegador:\n\n%(verification_url)s \n\nSi piensas que esto es un error, simplemente ignora este mensaje y sigue siendo un duende feliz." - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "¡Hubo un fallo al iniciar sesión!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "¿No tienes una cuenta?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "¡Crea una aquÃ!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "¿Olvidaste tu contraseña?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "¡Crea una cuenta!" - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Crear" +" >Create an account at this site</a>\n" +" or" +msgstr "\n >Crear una cuenta en este sitio</a>\n o" -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" -"\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" "\n" -"%(verification_url)s" -msgstr "Hola %(username)s,\n\npara activar tu cuenta de GNU MediaGoblin, abre la siguiente URL en tu navegador:\n\n%(verification_url)s " +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Instalar MediaGoblin en tu propio servidor</a>" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -612,13 +983,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Editando archivos adjuntos a %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Adjuntos" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Agregar adjunto" @@ -635,12 +1006,18 @@ msgstr "Cancelar" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Guardar cambios" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Cambiando el correo electrónico de %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -651,7 +1028,7 @@ msgid "Yes, really delete my account" msgstr "SÃ, borrar mi cuenta" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Eliminar permanentemente" @@ -668,10 +1045,14 @@ msgstr "Editando %(media_title)s " msgid "Changing %(username)s's account settings" msgstr "Cambio de %(username)s la configuración de la cuenta " -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "Borrar mi cuenta" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Correo electrónico" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -683,6 +1064,39 @@ msgstr "Editando %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Editando el perfil de %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "Hola,\n\nQuerÃamos verificar que eres %(username)s. Si ése es el caso, entonces \npor favor sigue el enlace de abajo para verificar tu nueva dirección de correo electrónico.\n\n%(verification_url)s\n\nSi no eres %(username)s o no solicitaste un cambio de dirección de correo electrónico,\npuedes ignorar este correo." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Nuevos comentarios" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "hace %(formatted_time)s" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Marcar todo como leÃdo" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -693,8 +1107,8 @@ msgstr "Contenido etiquetado con: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Descargar" @@ -717,7 +1131,8 @@ msgid "" msgstr "Tú puedes obtener un navegador más moderno que \n\tpueda reproducir el audio <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Archivo original" @@ -725,6 +1140,11 @@ msgstr "Archivo original" msgid "WebM file (Vorbis codec)" msgstr "Archivo WebM (códec Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Creado" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -735,70 +1155,267 @@ msgstr "Archivo WebM (códec Vorbis)" msgid "Image for %(media_title)s" msgstr "Imágenes para %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "Alternar Rotar" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "Archivo PDF" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "Perspectiva" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "Frente" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "Arriba" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "Lateral" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "Descargar modelo" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "Formato de Archivo" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "Altura del Objeto" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "Lo siento, este vÃdeo no funcionará\n porque tu navegador no soporta \n vÃdeo HTML5." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "¡Puedes conseguir un navegador moderno \n que pueda reproducir este vÃdeo en <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "Archivo WebM (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "Archivo WebM (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Aquà puedes llevar un seguimiento del estado del contenido que se está procesando en esta instancia." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Procesando contenido" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "No hay contenidos en procesamiento" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Estos archivos no pudieron ser procesados:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "¡No han fallado entradas!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Últimos 10 envÃos con éxito" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "¡Aún no hay entradas procesadas!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "Lo siento, no se ha encontrado el informe." + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "Volver al panel de informes" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "Informe" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "Comentario enviado" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "\nâ– Informe de <a href=\"%(user_url)s\">%(user_name)s</a> sobre contenidoâŽ" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "\nESTE CONTENIDO DEâŽ\n<a href=\"%(user_url)s\"> %(user_name)s</a>âŽ\nHA SIDO BORRADOâŽ" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "Resolver" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "Resolver este informe" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "Estado" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "RESUELTO" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "No puedes tomar una acción contra un administrador" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "Panel de informes" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "\nAquà puedes mirar informes abiertos que han sido enviados por usuarios.âŽ" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "Informes activos enviados" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "Ofensor" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "Cuándo se informó" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "Informe enviado por" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "Razón" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "\nInforme de comentario nº %(report_id)sâŽ" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "\nInforme de contenido nº %(report_id)sâŽ" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "No se han encontrado informes abiertos." + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "Informes cerrados" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "Resuelto" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "Acción tomada" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "\nInforme cerrado nº %(report_id)sâŽ" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "No se han encontrado informes cerrados." + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "Panel de usuarios" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "\nAquà puedes buscar usuarios de cara a tomar acciones punitivas sobre ellos.âŽ" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "Usuarios activos" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "ID" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "Cuándo se unió" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "Nº de comentarios enviados" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "No se han encontrado usuarios." #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Añadir una colección" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Añade tu contenido " @@ -817,11 +1434,6 @@ msgstr "%(collection_title)s por <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "Editar" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Borrar" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -833,7 +1445,7 @@ msgstr "¿Realmente deseas eliminar %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "¿Realmente quieres quitar %(media_title)s de %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Quitar" @@ -876,24 +1488,21 @@ msgstr "Contenido de <a href=\"%(user_url)s\">%(username)s</a>" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Explorando contenido de <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Añadir un comentario" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Añade un comentario " -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "en" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Previsualización del comentario" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Añadido en</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Agregado" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -918,85 +1527,107 @@ msgstr "Aquà puedes hacer un seguimiento del contenido que está siendo procesa msgid "Your last 10 successful uploads" msgstr "Tus últimos 10 envÃos exitosos" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Perfil de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Lo sentimos, no se encontró ese usuario." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "<h2>Enviar un informe</h2>" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Es necesario que verifiques tu cuenta mediante el correo de notiicación" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "¡Casi hemos terminado! Solo falta activar la cuenta." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "Informar sobre este comentario" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 -msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "En unos momentos te deberÃa llegar un correo electrónico con las instrucciones para hacerlo." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "Informar sobre esta entrada de contenido" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "En caso de que no:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Reenviar correo electrónico de verificación" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Alguien ya registró una cuenta con ese nombre de usuario, pero todavÃa no ha sido activada." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 #, python-format msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Si tú eres esa persona, pero has perdido tu correo electrónico de verificación, puedes <a href=\"%(login_url)s\">iniciar sesión</a> y reenviarlo." +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "\nâ– Publicado por <a href=\"%(user_url)s\"âŽ\nclass=\"comment_authorlink\">%(username)s</a>âŽ" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "Enviar informe" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 +#, python-format +msgid "%(username)s's profile" +msgstr "Perfil de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Aquà hay un lugar para que le cuentes a los demás sobre ti." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Editar perfil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Este usuario (todavÃa) no ha completado su perfil." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "Explorar colecciones" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Ver todo el contenido de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Aquà es donde estará ubicado tu contenido, pero parece que aún no has añadido nada." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Parece que aún no hay ningún contenido aquÃ..." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Es necesario que verifiques tu cuenta mediante el correo de notiicación" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "¡Casi hemos terminado! Solo falta activar la cuenta." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "En unos momentos te deberÃa llegar un correo electrónico con las instrucciones para hacerlo." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "En caso de que no:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Reenviar correo electrónico de verificación" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Alguien ya registró una cuenta con ese nombre de usuario, pero todavÃa no ha sido activada." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Si tú eres esa persona, pero has perdido tu correo electrónico de verificación, puedes <a href=\"%(login_url)s\">iniciar sesión</a> y reenviarlo." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "(borrar)" @@ -1045,50 +1676,85 @@ msgstr "Más nuevo" msgid "older" msgstr "Más viejo" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "Informar sobre contenido" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Marcado con" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "No se pudo leer el archivo de imagen." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "¡Ups!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Ha ocurrido un error" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Petición errónea" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "La petición enviada al servidor no es válida, por favor compruébala" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "Operación no permitida" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "¡Lo siento Dave, no puedo permitir que hagas eso!</p><p>Has intentado realizar una operación no permitida. ¿Has vuelto a intentar borrar todas las cuentas de usuario?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "Parece que no hay ninguna página en esta dirección. ¡Lo siento!</p><p>Si estás seguro de que la dirección es correcta, quizá han borrado o movido la página que estás buscando." +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "año" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "mes" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "semana" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "dÃa" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "hora" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minuto" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "Comentario" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Puedes usar <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> para el formato." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Puedes usar <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Markdown</a> para dar formato." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1110,73 +1776,84 @@ msgstr "-- Selecciona --" msgid "Include a note" msgstr "Incluir una nota" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "comentó tu publicación" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Puedes usar\n <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n Markdown</a> para dar formato." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "Razón del informe" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Lo siento, los comentarios están desactivados." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Ups, tu comentario estaba vacÃo." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "¡Tu comentario ha sido publicado!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "Por favor, revisa tus entradas e inténtalo de nuevo." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Tienes que seleccionar o añadir una colección" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "%s\" ya está en la colección \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" añadido a la colección \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Eliminaste el contenido" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "El contenido no se eliminó porque no marcaste que estabas seguro." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Estás a punto de eliminar un contenido de otro usuario. Procede con precaución." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Borraste el Ãtem de la colección." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "El Ãtem no fue removido porque no confirmaste que estuvieras seguro/a." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Estás a punto de borrar un Ãtem de la colección de otro usuario. Procede con cuidado." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Borraste la colección \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "La colección no fue borrada porque no confirmaste que estuvieras seguro/a." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Estás a punto de borrar la colección de otro usuario. Procede con cuidado." diff --git a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mo Binary files differindex 4b319ebd..24e95900 100644 --- a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po index 028ab5d4..6e549e0d 100644 --- a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po @@ -3,15 +3,15 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <amir007ag@gmail.com>, 2012. +# Numb <amir007ag@gmail.com>, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Persian (http://www.transifex.com/projects/p/mediagoblin/language/fa/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,253 +19,264 @@ msgstr "" "Language: fa\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Ù…ØªØ§Ø³ÙØ§Ù†Ù‡ØŒØ«Ø¨ØªÙ†Ø§Ù… به طور موقت غیر ÙØ¹Ø§Ù„ است." -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "نام کاربری" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "گذرواٰژه" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "آدرس ایمیل" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Ù…ØªØ§Ø³ÙØ§Ù†Ù‡ØŒØ«Ø¨ØªÙ†Ø§Ù… به طور موقت غیر ÙØ¹Ø§Ù„ است." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Ù…ØªØ§Ø³ÙØ§Ù†Ù‡ کاربری با این نام کاربری وجود دارد." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "ایمیل شما تایید شد.شما Ù…ÛŒ توانید ØØ§Ù„ا وارد شوید،نمایه خود را ویرایش کنید Ùˆ تصاویر خود را ثبت کنید!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "این کد تاییدیه یا شناسه کاربری صØÛŒØ نیست." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "ایمیل تاییدیه باز ارسال شد." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "" - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "عنوان" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "برچسب" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "زندگینامه" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "وبسایت" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "گذرواٰژه" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "شما در ØØ§Ù„ ویرایش رسانه کاربر دیگری هستید.با Ø§ØØªÛŒØ§Ø· عمل کنید" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "شما در ØØ§Ù„ ویرایش نمایه کاربر دیگری هستید.با Ø§ØØªÛŒØ§Ø· عمل کنید." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -273,15 +284,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "نام کاربری" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "آدرس ایمیل" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "آیا ØØ³Ø§Ø¨ کاربری ندارید؟" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "در اینجا یکی بسازید!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "" @@ -291,6 +489,10 @@ msgstr "" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -345,7 +547,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -358,215 +560,327 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 -msgid "Invalid file given for media type." -msgstr "ÙØ§ÛŒÙ„ÛŒ نا معتبر برای نوع رسانه داده شده." +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" -#: mediagoblin/submit/forms.py:26 -msgid "File" -msgstr "ÙØ§ÛŒÙ„" +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" -#: mediagoblin/submit/views.py:51 -msgid "You must provide a file." -msgstr "شما باید ÙØ§ÛŒÙ„ÛŒ ارايه بدهید." +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" -#: mediagoblin/submit/views.py:97 -msgid "Woohoo! Submitted!" -msgstr "هورا!ثبت شد!" +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/plugins/openid/views.py:106 #, python-format -msgid "Collection \"%s\" added!" +msgid "Verification of %s failed: %s" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 -msgid "Verify your email!" +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 -msgid "log out" +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 #: mediagoblin/templates/mediagoblin/auth/login.html:28 #: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 msgid "Log in" msgstr "ورود" -#: mediagoblin/templates/mediagoblin/base.html:79 -#, python-format -msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "ورود با خطا انجام شد!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 -msgid "Change account settings" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 -msgid "Media processing panel" -msgstr "پنل رسیدگی به رسانه ها" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 -msgid "Add media" +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 -#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 -msgid "Create new collection" +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format +#: mediagoblin/plugins/persona/views.py:144 msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +"You can't delete your only Persona email address unless you have a password " +"set." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "ÙØ§ÛŒÙ„ÛŒ نا معتبر برای نوع رسانه داده شده." + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" msgstr "" +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "ÙØ§ÛŒÙ„" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "شما باید ÙØ§ÛŒÙ„ÛŒ ارايه بدهید." + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "هورا!ثبت شد!" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" +msgstr "پنل رسیدگی به رسانه ها" + +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "ورود با خطا انجام شد!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "آیا ØØ³Ø§Ø¨ کاربری ندارید؟" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "در اینجا یکی بسازید!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 @@ -574,7 +888,7 @@ msgstr "" msgid "Create an account!" msgstr "ساخت یک ØØ³Ø§Ø¨ کاربری!" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "ساختن" @@ -589,6 +903,62 @@ msgid "" "%(verification_url)s" msgstr "سلام %(username)s,\n\nبرای ÙØ¹Ø§Ù„ سازی شناسه کاربری گنو مدیاگوبلین خود ،پیوند زیر را در مرورگر خود باز کنید.\n\n%(verification_url)s" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +971,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -624,12 +994,18 @@ msgstr "انصراÙ" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "ذخیره تغییرات" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -640,7 +1016,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "" @@ -657,10 +1033,14 @@ msgstr "ویرایش %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -672,6 +1052,39 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "در ØØ§Ù„ ویرایش نمایه %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -682,8 +1095,8 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "" @@ -706,7 +1119,8 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -714,6 +1128,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -724,70 +1143,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "" @@ -806,11 +1422,6 @@ msgstr "" msgid "Edit" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -822,7 +1433,7 @@ msgstr "" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -865,23 +1476,20 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>'s رسانه های" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -907,85 +1515,107 @@ msgstr "" msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "نمایه %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Ù…ØªØ§Ø³ÙØ§Ù†Ù‡ کاربر مورد نظر ÛŒØ§ÙØª نشد." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "به زودی ایمیلی ØØ§ÙˆÛŒ Ø´Ø±Ø Ú©Ø§Ø± ها برای شما ارسال خواهد شد." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "در این ØØ§Ù„ت وجود ندارد." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "باز ارسال ایمیل تاییدیه" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "اگر شما آن کاربر هستید Ùˆ ایمیل تایید خود را Ú¯Ù… کرده اید،, Ù…ÛŒ توانید <a href=\"%(login_url)s\">log in</a> Ùˆ دوباره آنرا Ø¨ÙØ±Ø³ØªÛŒØ¯.." +msgid "%(username)s's profile" +msgstr "نمایه %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "ویرایش نمایه" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "نمایش تمامی رسانه های %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "" +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "به زودی ایمیلی ØØ§ÙˆÛŒ Ø´Ø±Ø Ú©Ø§Ø± ها برای شما ارسال خواهد شد." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "در این ØØ§Ù„ت وجود ندارد." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "باز ارسال ایمیل تاییدیه" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "اگر شما آن کاربر هستید Ùˆ ایمیل تایید خود را Ú¯Ù… کرده اید،, Ù…ÛŒ توانید <a href=\"%(login_url)s\">log in</a> Ùˆ دوباره آنرا Ø¨ÙØ±Ø³ØªÛŒØ¯.." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1034,49 +1664,84 @@ msgstr "" msgid "older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "اوه" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1099,73 +1764,84 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo Binary files differindex ada992ce..98777a9a 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 b4c76bd2..c0734f2d 100644 --- a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po @@ -3,22 +3,23 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <a5565930@nepwk.com>, 2011. -# <alexispay@gmail.com>, 2012. -# <chesuidayeur@yahoo.fr>, 2011. -# <crash_bibit@hotmail.com>, 2013. -# <joehillen@gmail.com>, 2011. -# Laurent Pointecouteau <hell_pe@no-log.org>, 2013. -# <marktraceur@gmail.com>, 2011. -# <maxineb@members.fsf.org>, 2011. -# <transifex@wandborg.se>, 2011. -# Valentin Villenave <valentin@villenave.net>, 2011. +# ianux <a5565930@nepwk.com>, 2011 +# alcazar <alexispay@gmail.com>, 2012 +# chesuidayeur <chesuidayeur@yahoo.fr>, 2011 +# Bibit <crash_bibit@hotmail.com>, 2013 +# Fubik, 2013 +# joehillen <joehillen@gmail.com>, 2011 +# hellpe <hell_pe@no-log.org>, 2013 +# MarkTraceur <marktraceur@gmail.com>, 2011 +# maxineb <maxineb@members.fsf.org>, 2011 +# joar <transifex@wandborg.se>, 2011 +# Valentin Villenave <valentin@villenave.net>, 2011 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: French (http://www.transifex.com/projects/p/mediagoblin/language/fr/)\n" "MIME-Version: 1.0\n" @@ -28,269 +29,467 @@ msgstr "" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "Nom d'utilisateur ou adresse de courriel invalide." - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "L'inscription n'est pas activée sur ce serveur, désolé." -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Nom d'utilisateur" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Mot de passe" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "Désolé, l'authentification est désactivée sur ce serveur." -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Adresse e-mail" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "Nom d'utilisateur ou adresse de courriel invalide." -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Nom d'utilisateur ou email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "Ce champ n'accepte pas les adresses email." -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "L'inscription n'est pas activée sur ce serveur, désolé." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "Ce champ nécessite une adresse email." -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Un utilisateur existe déjà avec ce nom, désolé." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Désolé, il existe déjà un utilisateur ayant cette adresse e-mail." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "La clé de vérification ou l'identifiant de l'utilisateur est incorrect." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Votre adresse e-mail a bien été vérifiée. Vous pouvez maintenant vous identifier, modifier votre profil, et soumettre des images !" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "La clé de vérification ou le nom d'utilisateur est incorrect." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 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:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Votre adresse e-mail a déjà été vérifiée !" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "E-mail de vérification renvoyé." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "Nom d'utilisateur introuvable." - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Un email contenant les instructions pour changer votre mot de passe viens de vous être envoyé" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Impossible d'envoyer un email de récupération de mot de passe : votre compte est inactif ou bien l'email de votre compte n'a pas été vérifiée." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Vous pouvez maintenant vous connecter avec votre nouveau mot de passe." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titre" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Descriptif pour ce travail" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Vous pouvez utiliser\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> pour le formattage." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Tags" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Séparez les champs avec des virgules." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Légende" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "La légende ne peut pas être laissée vide." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Le titre présent dans l'URL du média. Vous n'avez généralement pas besoin de le modifier" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Licence" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Site web" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Cette adresse contiens des erreurs" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Ancien mot de passe." - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Entrez votre ancien mot de passe pour prouver que vous êtes bien le propriétaire de ce compte." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Me prévenir par email lorsque d'autres commentent mes médias" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nouveau mot de passe" +msgid "Enable insite notifications about events." +msgstr "Activer les notifications sur le site concernant les évènements." -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" -msgstr "" +msgstr "Préférence de licence" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" - -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Me prévenir par email lorsque d'autres commentent mes médias" +msgstr "Cette licence sera appliquée par défaut à vos contributions." -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "Le titre ne peut être vide" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Description de cette collection" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "Le titre affiché dans l'URL de la collection. Vous n'avez généralement pas besoin d'y toucher." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Ancien mot de passe." + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Entrez votre ancien mot de passe pour prouver que vous êtes bien le propriétaire de ce compte." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nouveau mot de passe" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Nouvelle adresse email" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Mot de passe" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Entrez votre mot de passe pour prouver que vous possédez ce compte." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." -msgstr "Une entrée existe déjà pour cet utilisateur avec la même légende." +msgstr "Une entrée avec la même légende existe déjà pour cet utilisateur." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Vous vous apprêtez à modifier le média d'un autre utilisateur. Veuillez prendre garde." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "Vous avez ajouté la pièce jointe %s !" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "Vous ne pouvez modifier que votre propre profil." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Vous vous apprêtez à modifier le profil d'un utilisateur. Veuillez prendre garde." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Les changements apportés au profile ont étés sauvegardés" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Mauvais mot de passe" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Les changements des préférences du compte ont étés sauvegardés" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "Vous devez confirmer la suppression de votre compte." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Vous avez déjà une collection appelée \"%s\" !" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." -msgstr "" +msgstr "Une collection avec la même légende existe déjà pour cet utilisateur." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Vous éditez la collection d'un autre utilisateurs. Faites attention." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Votre adresse email a bien été validée." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Mauvais mot de passe" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Impossible de lier le thème... Aucun thème associé\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "Aucun répertoire \"asset\" pour ce thème\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "Ne peut pas lier \"%s\" : %s existe et n'est pas un lien symbolique\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "Saute \"%s\"; déjà défini.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "Vieux lien trouvé pour \"%s\"; suppression.\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.<br/>Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "Cookie CSRF non présent. Cela est vraisemblablement l’œuvre d'un bloqueur de cookies ou autres.<br/>Veuillez vous assurer d'autoriser les cookies pour ce domaine." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Désolé, mais je ne prends pas en charge cette extension de fichier :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "unoconv n'arrive pas à s'exécuter, vérifiez le fichier log" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "L'encodage de la vidéo à échoué" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "a commenté votre post" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "Inscrit aux commentaires sur %s !" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "Vous ne recevrez pas de notifications pour les commentaires sur %s." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "Doit fournir un oauth_token." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Nom d'utilisateur" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Adresse e-mail" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Nom d'utilisateur ou email" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "Rester connecter" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Nom d'utilisateur ou email" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Si cette adresse email (sensible à la casse !) est enregistrée, un email a été envoyé avec les instructions pour changer votre mot de passe." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Nom d'utilisateur introuvable." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Un email contenant les instructions pour changer votre mot de passe viens de vous être envoyé" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Impossible d'envoyer un email de récupération de mot de passe : votre compte est inactif ou bien l'email de votre compte n'a pas été vérifiée." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "L'identifiant de l'utilisateur est incorrect." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Vous pouvez maintenant vous connecter avec votre nouveau mot de passe." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Votre mot de passe a correctement été changé" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Enregistrez votre nouveau mot de passe" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Enregistrez votre mot de passe" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Changement du mot de passe de %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Sauvegarder" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Pas encore de compte ?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Créez-en un ici !" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Récupérer le mot de passe" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Envoyer les instructions" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Vous avez oublié votre mot de passe ?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Position" @@ -300,6 +499,10 @@ msgstr "Position" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Regarder sur <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Autoriser" @@ -314,7 +517,7 @@ msgstr "Nom" #: mediagoblin/plugins/oauth/forms.py:35 msgid "The name of the OAuth client" -msgstr "" +msgstr "Le nom du client OAuth" #: mediagoblin/plugins/oauth/forms.py:36 msgid "Description" @@ -338,7 +541,7 @@ msgid "" " <strong>Public</strong> - The client can't make confidential\n" " requests to the GNU MediaGoblin instance (e.g. client-side\n" " JavaScript client)." -msgstr "" +msgstr "<strong>Confidentiel</strong> - Le client peut envoyer des requêtes à l'instance de GNU MediaGoblin qui ne peuvent pas être interceptées par le user agent (un client côté serveur par exemple).<br />\n<strong>Public</strong> - Le client ne peut pas envoyer des requêtes confidentielles à l'instance de GNU MediaGoblin (un client JavaScript côté client par exemple)." #: mediagoblin/plugins/oauth/forms.py:52 msgid "Redirect URI" @@ -354,7 +557,7 @@ msgstr "L'URI de redirection pour l'application, ce champ est <strong>requis</st msgid "This field is required for public clients" msgstr "Ce champ est requis pour les clients publics" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Le client {0} as été enregistré !" @@ -364,226 +567,338 @@ msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "Vos clients OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Ajouter" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "Désolé, un compte est déjà enregistré avec cet OpenID." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "Désolé, le serveur OpenID n'a pas pu être trouvé." + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "Aucun service OpenID n'a été trouvé pour %s" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "La vérification de %s a échoué : %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Vérification annulée" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "Votre url OpenID a été correctement enregistrée." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "Vous ne pouvez pas supprimer votre seul URL OpenID sauf si vous avez défini un mot de passe" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "Cet OpenID n'est pas relié à ce compte." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "OpenID a été correctement supprimé." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Ajouter un OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Supprimer un OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Effacer" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "S'identifier" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "La connexion a échoué!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "Ou se connecter avec un mot de passe !" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "Ou se connecter avec OpenID !" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "Ou s'enregistrer avec OpenID !" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "Désolé, un compte est déjà enregistré avec cet email Persona." + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "L'adresse email Persona a correctement été supprimée." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "Vous ne pouvez pas supprimer votre seul email Persona sauf si vous avez défini un mot de passe." + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "Cette adresse email Persona n'est pas liée à ce compte." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "Désolé, un compte est déjà enregistré avec cette adresse email Persona." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Votre adresse email Persona a bien été enregistrée." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "Supprimer une adresse email Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "Ajouter une adresse email Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "Ou se connecter avec Persona !" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "Ou s'enregistrer avec Persona !" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Le fichier envoyé ne correspond pas au type de média." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "La copie vers le stockage public a échoué." + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Fichier" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Il vous faut fournir un fichier." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Youhou, c'est envoyé !" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "Collection \"%s\" ajoutée !" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Vérifiez votre adresse e-mail !" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "Déconnexion" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "S'identifier" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" -msgstr "" +msgstr "Compte de <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Changer les paramètres du compte" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Panneau pour le traitement des médias" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "Se déconnecter" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Ajouter des médias" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Créer une nouvelle collection" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." -msgstr "Disponible sous la licence <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Code source</a> disponible." - -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Explorer" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Bonjour, et bienvenue sur ce site MediaGoblin !" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." -msgstr "Ce site fait tourner <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un logiciel d'hébergement de média extraordinairement génial." - -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." -msgstr "Pour ajouter vos propres médias, commenter, et bien plus encore, vous pouvez vous connecter avec votre compte MediaGoblin" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" -msgstr "Vous n'en avez pas ? C'est facile !" - -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Tout derniers media" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Ici, vous pouvez suivre l'état des médias en cours de traitement par cette instance." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Médias en transformation" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Aucun média en transformation" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Le traitement de ces ajouts a échoué :" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Autorisation" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Aucune entrée ayant échoué !" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "Autoriser" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "10 derniers envois terminés" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Vous êtes connecté en tant que" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Aucune entrée traitée jusqu'à présent !" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "Voulez-vous autoriser" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Enregistrez votre nouveau mot de passe" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "une application inconnue" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Enregistrez votre mot de passe" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "pour accéder à votre compte ?" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Récupérer le mot de passe" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Les applications ayant accès à votre compte peuvent :" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Envoyer les instructions" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "Poster un nouveau média sous votre nom" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Bonjour %(username)s,\n\nPour changer votre mot de passe GNU MediaGoblin, ouvrez l'URL suivante dans \nvotre navigateur internet :\n\n%(verification_url)s\n\nSi vous pensez qu'il s'agit d'une erreur, ignorez simplement cet email et restez\nun goblin heureux !" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "Voir vos informations (profile, médias, etc...)" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "La connexion a échoué!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "Modifier vos informations" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Pas encore de compte ?" +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Créez-en un ici !" +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Vous avez oublié votre mot de passe ?" +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Copier-coller ceci dans votre client :" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "Créer un compte !" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "Créer" @@ -598,6 +913,62 @@ msgid "" "%(verification_url)s" msgstr "Bonjour %(username)s,\n\npour activer votre compte sur GNU MediaGoblin, veuillez vous rendre à l'adresse suivante avec votre navigateur web:\n\n%(verification_url)s" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "Propulsé par <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, un projet <a href=\"http://gnu.org/\">GNU</a>." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "Disponible sous la licence <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Code source</a> disponible." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Explorer" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Bonjour, et bienvenue sur ce site MediaGoblin !" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "Ce site fait tourner <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un logiciel d'hébergement de média extraordinairement génial." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "Pour ajouter vos propres médias, commenter, et bien plus encore, vous pouvez vous connecter avec votre compte MediaGoblin" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "Vous n'en avez pas ? C'est facile !" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "\n>Créer un compte sur ce site</a>\nou" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n<a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Installer MediaGoblin sur votre propre serveur</a>" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -610,13 +981,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Éditer les pièces jointes de %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Pièces jointes" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Ajouter une pièce jointe" @@ -633,23 +1004,29 @@ msgstr "Annuler" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Enregistrer les modifications" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Changement de l'email de %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" -msgstr "" +msgstr "Réellement supprimer l'utilisateur \"%(user_name)s\" et tous les médias/commentaires liés ?" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 msgid "Yes, really delete my account" -msgstr "" +msgstr "Oui, supprimer réellement mon compte" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Supprimer définitivement" @@ -666,9 +1043,13 @@ msgstr "Modification de %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "Changement des préférences du compte de %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" -msgstr "" +msgstr "Supprimer mon compte" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Email" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format @@ -681,6 +1062,39 @@ msgstr "Modification de %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Modification du profil de %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "Bonjour,\n\nNous voulons vérifier que vous êtes %(username)s. Si cela est bien le cas, veuillez suivre le lien ci-dessous pour vérifier votre nouvelle adresse email.\n\n%(verification_url)s\n\nSi vous n'êtes pas %(username)s ou n'avez pas demandé un changement d'adresse email, vous pouvez ignorer cet email." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Nouveaux commentaires" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "Il y a %(formatted_time)s" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Marquer tous lus" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -691,8 +1105,8 @@ msgstr "Médias taggés avec : %(tag_name)s " #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Télécharger" @@ -715,7 +1129,8 @@ msgid "" msgstr "Vous pouvez obtenir un navigateur à jour capable de lire cette vidéo sur <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Fichier original" @@ -723,6 +1138,11 @@ msgstr "Fichier original" msgid "WebM file (Vorbis codec)" msgstr "fichier WebM (codec Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Créé" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -733,77 +1153,274 @@ msgstr "fichier WebM (codec Vorbis)" msgid "Image for %(media_title)s" msgstr "Image de %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "Fichier PDF" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" -msgstr "" +msgstr "Haut" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" -msgstr "" +msgstr "Côté" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" -msgstr "" +msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" -msgstr "" +msgstr "Télécharger le modèle" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" -msgstr "" +msgstr "Format de fichier" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" -msgstr "" +msgstr "Hauteur de l'objet" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." -msgstr "" +msgstr "Désolé, cette vidéo ne marchera pas parce que votre navigateur web ne supporte pas les vidéos HTML5." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" +msgstr "Vous pouvez télécharger un navigateur web moderne qui peut lire cette vidéo à <a href=\"http://getfirefox.com\">http://getfirefox.com</a> !" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "Fichier WebM (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Ici, vous pouvez suivre l'état des médias en cours de traitement par cette instance." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Médias en transformation" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Aucun média en transformation" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Le traitement de ces ajouts a échoué :" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Aucune entrée ayant échoué !" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "10 derniers envois terminés" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Aucune entrée traitée jusqu'à présent !" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "fichier WebM (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Ajouter une collection" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Ajoutez votre média" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:30 #, python-format msgid "%(collection_title)s (%(username)s's collection)" -msgstr "" +msgstr "%(collection_title)s (collection de %(username)s)" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:39 #, python-format @@ -815,11 +1432,6 @@ msgstr "%(collection_title)s de <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "Éditer" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Effacer" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -831,19 +1443,19 @@ msgstr "Voulez-vous vraiment supprimer %(title)s ?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Voulez vous vraiment retirer %(media_title)s de %(collection_title)s ?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Retirer" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 #, python-format msgid "%(username)s's collections" -msgstr "" +msgstr "Collections de %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" -msgstr "" +msgstr "Collections de <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -862,7 +1474,7 @@ msgstr "Medias de %(username)s" msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "Media de <a href=\"%(user_url)s\">%(username)s</a> avec le tag <a href=\"%(tag_url)s\">%(tag)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -874,30 +1486,27 @@ msgstr "Médias de <a href=\"%(user_url)s\">%(username)s</a>" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Parcourir les médias de <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Ajouter un commentaire" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Ajouter ce commentaire" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "à " +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Prévisualisation du commentaire" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Ajouté le</h3>\n<p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Ajouté" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 #, python-format msgid "Add “%(media_title)s†to a collection" -msgstr "" +msgstr "Ajouter “%(media_title)s†à une collection" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" @@ -916,88 +1525,110 @@ msgstr "Vous pouvez suivre l'état des médias en cours de traitement pour votre msgid "Your last 10 successful uploads" msgstr "Vos 10 derniers envois réussis" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "profil de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Impossible de trouver cet utilisateur, désolé." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Vérification d'email nécessaire" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Presque fini ! Votre compte a encore besoin d'être activé." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Un e-mail devrait vous parvenir dans quelques instants ; il vous indiquera comment procéder." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Si la vérification n'est pas arrivée à bon port :" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Renvoyer l'e-mail de vérification" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Quelqu'un a enregistré un compte avec ce nom, mais il doit encore être activé." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Si c'est de vous qu'il s'agit, mais que vous avez perdu l'e-mail de vérification, vous pouvez vous <a href=\"%(login_url)s\">identifier</a> et le renvoyer." +msgid "%(username)s's profile" +msgstr "profil de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Voici un endroit pour parler aux autres de vous-même." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Modifier le profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Cet utilisateur n'a pas (encore) rempli son profil." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" -msgstr "" +msgstr "Parcourir les collections" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Voir tous les médias de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "C'est là où vos médias apparaîssent, mais vous ne semblez pas avoir encore ajouté quoi que ce soit." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Il ne semble pas y avoir de média là , pour l'instant ..." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Vérification d'email nécessaire" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Presque fini ! Votre compte a encore besoin d'être activé." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Un e-mail devrait vous parvenir dans quelques instants ; il vous indiquera comment procéder." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Si la vérification n'est pas arrivée à bon port :" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Renvoyer l'e-mail de vérification" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Quelqu'un a enregistré un compte avec ce nom, mais il doit encore être activé." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Si c'est de vous qu'il s'agit, mais que vous avez perdu l'e-mail de vérification, vous pouvez vous <a href=\"%(login_url)s\">identifier</a> et le renvoyer." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" -msgstr "" +msgstr "(supprimer)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" @@ -1005,7 +1636,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "Ajouter à une collection" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 @@ -1043,50 +1674,85 @@ msgstr "le plus récent" msgid "older" msgstr "le plus vieux" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Taggé avec" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Impossible de lire l'image." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Zut !" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Une erreur est survenue" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Mauvaise requête" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "La requête envoyée au serveur est non valide, veuillez la vérifier" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "Opération non autorisée" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "Je regrette Dave, cela m'est malheureusement impossible !</p><p>Vous avez essayé d'effectuer une action pour laquelle vous n'avez pas de permission. Avez-vous tenté de supprimer tous les comptes utilisateur à nouveau ?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "Il ne semble pas y avoir de page à cette adresse. Désolé ! </p><p>Si vous êtes sûr que l'adresse est correcte, peut-être que la page que vous recherchez a été déplacée ou supprimée." +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "année" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "mois" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "semaine" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "jour" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "heure" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minute" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" -msgstr "" +msgstr "Commenter" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Vous pouvez utilisez les <a href=\"http://daringfireball.net/projects/markdown/basics\">Balises</a> pour la mise en page." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Vous pouvez utiliser <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Markdown</a> pour le formatage." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1098,7 +1764,7 @@ msgstr "Je suis certain de vouloir retirer cet élément de la collection" #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "Collection" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" @@ -1108,73 +1774,84 @@ msgstr "-- Sélectionner --" msgid "Include a note" msgstr "Inclure une note" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "a commenté votre post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Vous pouvez utiliser\n<a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\nMarkdown</a> pour le formatage." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Désolé, les commentaires sont désactivés." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Oups, votre commentaire était vide." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Votre commentaire a été posté !" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "Veuillez vérifier vos entrées et réessayer." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Vous devez sélectionner ou ajouter une collection" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" est déjà dans la collection \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" as été ajouté à la collection \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Vous avez supprimé le media." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 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:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Vous êtes sur le point de supprimer des médias d'un autre utilisateur. Procédez avec prudence." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Vous avez supprimé cet élément de la collection." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "L'élément n'as pas été supprimé car vous n'avez pas confirmé votre certitude." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Vous vous apprêtez à supprimer un élément de la collection d'un autre utilisateur. Procédez avec attention." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Vous avez supprimé la collection \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "La collection n'as pas été supprimée car vous n'avez pas confirmé votre certitude" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Vous vous apprêtez à supprimer la collection d'un autre utilisateur. Procédez avec attention." diff --git a/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mo Binary files differindex ce2963f7..ff7f26d7 100644 --- a/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po index 12d932c8..2ee7f3dd 100644 --- a/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po @@ -3,16 +3,17 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <genghiskhan@gmx.ca>, 2012. -# Isratine Citizen <genghiskhan@gmx.ca>, 2012. +# GenghisKhan <genghiskhan@gmx.ca>, 2013 +# GenghisKhan <genghiskhan@gmx.ca>, 2012 +# GenghisKhan <genghiskhan@gmx.ca>, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" -"Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-02 09:28-0600\n" +"PO-Revision-Date: 2013-12-02 17:53+0000\n" +"Last-Translator: GenghisKhan <genghiskhan@gmx.ca>\n" +"Language-Team: Hebrew (http://www.transifex.com/projects/p/mediagoblin/language/he/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -20,269 +21,467 @@ msgstr "" "Language: he\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" - -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "×œ×¦×¢×¨× ×•, ×¨×™×©×•× ×”×™× ×• ×ž× ×•×˜×¨×œ על שרת ×–×”." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "×©× ×ž×©×ª×ž×©" +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "×œ×¦×¢×¨× ×•, דיווח ×”×™× ×• ×ž× ×•×˜×¨×œ×™× ×¢×œ שרת ×–×”." -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "סיסמה" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "×œ×¦×¢×¨× ×•, ×ימות ×”×™× ×• ×ž× ×•×˜×¨×œ על שרת ×–×”." -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "כתובת דו×״ל" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "×©× ×ž×©×ª×ž×© ×ו דו×״ל שגויי×." -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "×©× ×ž×©×ª×ž×© ×ו דו×״ל" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "שדה ×–×” ×œ× ×œ×•×§×— כתובות דו×״ל." -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "צר לי, ×¨×™×©×•× ×”×™× ×• ×ž× ×•×˜×¨×œ על שרת ×–×”." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "שדה ×–×” מצריך כתובת דו×״ל." -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." -msgstr "צר לי, משתמש ×¢× ×©× ×–×” כבר ×§×™×™×." +msgstr "×œ×¦×¢×¨× ×•, משתמש ×¢× ×©× ×–×” כבר ×§×™×™×." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." -msgstr "צר לי, משתמש ×¢× ×“×•×״ל ×–×” כבר ×§×™×™×." +msgstr "×œ×¦×¢×¨× ×•, משתמש ×¢× ×›×ª×•×‘×ª דו×״ל זו כבר ×§×™×™×." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "מפתח ×”×ימות ×ו מזהה המשתמש ××™× ×• מדויק." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "כתובת הדו×״ל שלך ×ומתה. כעת ב×פשרותך להתחבר, לערוך ×ת ×“×™×•×§× ×š, ולשלוח ×ª×ž×•× ×•×ª!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "מפתח ×”×ימות ×ו זהות משתמש ×”×™× × ×©×’×•×™×™×" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "עליך להתחבר על ×ž× ×ª ×©× ×“×¢ ×ל מי לשלוח ×ת הדו×״ל!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "כבר ×ימתת ×ת כתובת הדו×״ל שלך!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "שלח שוב ×ת דו×״ל ×”×ימות שלך." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "דו×״ל × ×©×œ×— בצירוף הור×ות ×‘× ×•×’×¢ לכיצד × ×™×ª×Ÿ ×œ×©× ×•×ª ×ת סיסמתך." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "×œ× ×”×™×” × ×™×ª×Ÿ לשלוח דו×״ל לשחזור סיסמה מ×חר ×•×©× ×”×ž×©×ª×ž×© שלך ××™× ×• פעיל ×ו שכתובת הדו×״ל של ×—×©×‘×•× ×š ×œ× ×ומתה." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "כעת ביכולתך להתחבר ב×מצעות סיסמתך החדשה." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "כותרת" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "תי×ור של מל××›×” זו" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." -msgstr "ביכולתך להשתמש בתחביר\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> לעיצוב." +msgstr "ב×פשרותך להשתמש בתחביר\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> לעיצוב." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "תגיות" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "הפרד תגיות בעזרת פסיקי×." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "חשופית" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "החשופית ×œ× ×™×›×•×œ×” להיות ריקה" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "×זור הכותרת של כתובת מדיה זו. לרוב ×ין הכרח ×œ×©× ×•×ª ×ת חלק ×–×”." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "רשיון" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "ביו" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "×תר רשת" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "כתובת זו מכילה שגי×ות" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "סיסמה ×™×©× ×”" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "הזן ×ת סיסמתך ×”×™×©× ×” כדי להוכיח ש×תה ×”×‘×¢×œ×™× ×©×œ חשבון ×–×”." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "שלח לי דו×״ל ×›×שר ××—×¨×™× ×ž×’×™×‘×™× ×¢×œ המדיה שלי" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "סיסמה חדשה" +msgid "Enable insite notifications about events." +msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" -msgstr "" +msgstr "עדיפות רשיון" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" +msgstr "×–×” ×™×”×™×” הרשיוןן המשתמט (ברירת מחדל) שלך בטופסי העל××”." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "שלח לי דו×״ל ×›×שר ××—×¨×™× ×ž×’×™×‘×™× ×¢×œ המדיה שלי" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "הכותרת ×œ× ×™×›×•×œ×” להיות ריקה" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "תי×ור ×וסף ×–×”" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "×זור הכותרת של כתובת ×וסף ×–×”. לרוב ×ין הכרח ×œ×©× ×•×ª ×ת חלק ×–×”." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "סיסמה ×™×©× ×”" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "הזן ×ת סיסמתך ×”×™×©× ×” כדי להוכיח ש×תה ×”×‘×¢×œ×™× ×©×œ חשבון ×–×”." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "סיסמה חדשה" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "כתובת דו×״ל חדשה" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "סיסמה" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "הזן ×ת הסיסמה שלך כדי להוכיח ×›×™ ×תה ×”×‘×¢×œ×™× ×©×œ חשבון ×–×”." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "רשומה ×¢× ×—×©×•×¤×™×ª זו כבר קיימת עבור משתמש ×–×”." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "×תה עורך מדיה של משתמש ×חר. המשך בזהירות." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "הוספת ×ת התצריף %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." -msgstr "" +msgstr "ב×פשרותך לערוך רק ×ת הדיוקן שלך." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "×תה עורך דיוקן של משתמש. המשך בזהירות." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "×©×™× ×•×™×™ דיוקן × ×©×ž×¨×•" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "סיסמה שגויה" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "הגדרות חשבון × ×©×ž×¨×•" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." -msgstr "" +msgstr "עליך ל×מת ×ת המחיקה של ×—×©×‘×•× ×š." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "כבר יש לך ×וסף שקרוי ×‘×©× \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "×וסף ×¢× ×—×©×•×¤×™×ª זו כבר ×§×™×™× ×¢×‘×•×¨ משתמש ×–×”." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "×תה עורך ×וסף של משתמש ×חר. המשך בזהירות." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "כתובת הדו×״ל שלך ×ומתה." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "סיסמה שגויה" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "×œ× × ×™×ª×Ÿ לקשר ×ל מוטיב... ×œ× ×”×•×’×“×¨ מוטיב\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "×ין מדור × ×›×¡ עבור מוטיב ×–×”\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "בכל ×ופן, קישור מדור symlink × ×ž×¦×; הוסר.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "×œ× ×”×™×ª×” ×פשרות לקשר ×ת \"%s\": %s ×§×™×™× ×•××™× ×• קישור סמלי (symlink)\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "מדלג על \"%s\"; כבר מוגדר.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "קישור ישן × ×ž×¦× ×¢×‘×•×¨ \"%s\"; מסיר כעת.\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.<br/>Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "עוגיית CSRF ×œ× × ×•×›×—×ª. ×–×” קרוב לווד××™ × ×•×‘×¢ ×ž×©×•× ×—×•×¡× ×¢×•×’×™×™×” ×ו משהו ×‘×¡×’× ×•×Ÿ.<br/>הבטח קביעה של עוגיות עבור ×ª×—×•× ×–×”." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" -msgstr "צר לי, ××™× × ×™ תומך בטיפוס קובץ ×–×” :(" +msgstr "×œ×¦×¢×¨× ×•, ××™× × ×™ תומך בטיפוס קובץ ×–×” :(" + +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "unoconv × ×›×©×œ לפעול, בדוק קובץ יומן" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "המרת ויד×ו × ×›×©×œ×”" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "הסר פריבילגיה" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "×סור ×ת המשתמש" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "שלח ×ל המשתמש הודעה" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "מחק ×ת התוכן" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "משתמש ×™×סר עד:" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "מדוע ×תה ×וסר ×ת משתמש ×–×”?" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "ב×יזו פעולה ×ª× ×§×•×˜ כדי לפתור ×ת דיווח ×–×”?" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "×ילו פריבילגיות ×תה תסיר?" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "×זהרה מ×ת" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "הגיב/×” על פרסומך" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "×”×™×¨×©× ×ל תגובות בתוך %s!" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "×תה ×œ× ×ª×§×‘×œ התר×ות עבור הודעות על %s." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "יש לספק oauth_token." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "×œ× × ×ž×¦××” ×ות בקשה." + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "×œ×¦×¢×¨× ×•, גודל הקובץ גדול מדי." + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "×œ×¦×¢×¨× ×•, העל×ת קובץ ×–×” ×ª×©×™× ×ותך למעלה מן גבול ההעל××” שלך." + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "×œ×¦×¢×¨× ×•, חצית ×ת מגבלת ההעל××”." + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "×©× ×ž×©×ª×ž×©" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "כתובת דו×״ל" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "×©× ×ž×©×ª×ž×© ×ו דו×״ל" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "היש×ר מחובר" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "×©× ×ž×©×ª×ž×© ×ו דו×״ל" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "במידה וכתובת הדו×״ל הזו (תלוי רישיות!) רשומה דו×״ל × ×©×œ×— ×¢× ×”×•×¨×ות ×‘× ×•×’×¢ לכיצד ×œ×©× ×•×ª ×ת סיסמתך." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "×œ× ×”×™×” × ×™×ª×Ÿ ×œ×ž×¦×•× ×ž×™×©×”×• ×¢× ×©× ×ž×©×ª×ž×© ×–×”." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "דו×״ל × ×©×œ×— בצירוף הור×ות ×‘× ×•×’×¢ לכיצד × ×™×ª×Ÿ ×œ×©× ×•×ª ×ת סיסמתך." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "×œ× ×”×™×” × ×™×ª×Ÿ לשלוח דו×״ל לשחזור סיסמה מ×חר ×•×©× ×”×ž×©×ª×ž×© שלך ××™× ×• פעיל ×ו שכתובת הדו×״ל של ×—×©×‘×•× ×š ×œ× ×ומתה." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "מזהה המשתמש ××™× ×• מדויק." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "כעת ב×פשרותך להתחבר ב×מצעות סיסמתך החדשה." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "××™× ×š משתמש פעיל עוד. ×× × ×¦×•×¨ קשר ×¢× ×ž× ×”×œ המערכת כדי לתפעל מחדש ×ת ×—×©×‘×•× ×š." + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "סיסמתך ×©×•× ×ª×” בהצלחה" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "הגדר ×ת סיסמתך החדשה" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "הגדר סיסמה" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "×ž×©× ×” כעת ×ת הסיסמה של %(username)s'" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "שמור" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "×ין לך חשבון עדיין?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "צור חשבון ×›×ן!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "×©× ×” ×ת הסיסמה שלך." + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "שחזור סיסמה" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "שלח הור×ות" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "שכחת ×ת סיסמתך?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "מיקו×" @@ -290,7 +489,11 @@ msgstr "מיקו×" #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52 #, python-format msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" -msgstr "הצגה ×צל <a href=\"%(osm_url)s\">OpenStreetMap</a>" +msgstr "הצג בתוך <a href=\"%(osm_url)s\">OpenStreetMap</a>" + +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "התחבר כדי ליצור חשבון!" #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" @@ -316,7 +519,7 @@ msgstr "תי×ור" msgid "" "This will be visible to users allowing your\n" " application to authenticate as them." -msgstr "" +msgstr "×–×” יר××” ×œ×ž×©×ª×ž×©×™× ×©×ž×ª×™×¨×™×\n ×œ×™×™×©×•×ž×™× ×©×œ×š ל×מת ×ות×." #: mediagoblin/plugins/oauth/forms.py:40 msgid "Type" @@ -346,101 +549,370 @@ msgstr "" msgid "This field is required for public clients" msgstr "שדה ×–×” ×”×™× ×• דרוש עבור לקוחות פומביי×" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "הלקוח {0} × ×¨×©×!" #: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 msgid "OAuth client connections" -msgstr "" +msgstr "חיבורי לקוח OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "לקוחות OAuth שלך" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "הוסף" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "×œ×¦×¢×¨× ×•, ×§×™×™× ×›×‘×¨ חשבון ×שר ×¨×©×•× ×¢× OpenID." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "×œ×¦×¢×¨× ×•, שרת OpenID ×œ× ×”×™×” יכול להימצ×" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "×œ× × ×ž×¦× ×©×™×¨×•×ª OpenID עבור %s" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "×ימות של %s × ×›×©×œ: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "×ימות בוטל" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "כתובת OpenID × ×©×ž×¨×” בהצלחה." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "×ין ב×פשרותך למחוק כתובת ×›×שר זו היחידה שלך ××œ× ×× ×›×Ÿ הגדרת סיסמה." + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "כתובת זו ×œ× ×¨×©×•×ž×” לחשבון ×–×”." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "OpenID הוסר בהצלחה." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "הוסף OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "מחק OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "מחק" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "התחברות" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "התחברות × ×›×©×œ×”!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "התחבר כדי ליצור חשבון!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "×ו התחבר בעזרת סיסמה!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "×ו התחבר ×¢× OpenID!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "×ו ×”×™×¨×©× ×‘×¢×–×¨×ª OpenID!" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "×œ×¦×¢×¨× ×•, ×§×™×™× ×›×‘×¨ חשבון ×שר ×¨×©×•× ×œ×ישיות דו×״ל זו." + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "כתובת דו×״ל ×ישיות הוסרה בהצלחה." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "×ין ב×פשרותך למחוק כתובת דו×״ל ×ישיות ×›×שר זו היחידה שלך ××œ× ×× ×›×Ÿ הגדרת סיסמה." + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "כתובת דו×״ל ×ישיות זו ×œ× ×¨×©×•×ž×” לחשבון ×–×”." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "×œ×¦×¢×¨× ×•, ×§×™×™× ×›×‘×¨ חשבון ×שר ×¨×©×•× ×¢× ×ישיות כתובת דו×״ל זו." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "כתובת דו×״ל ×ישיות × ×©×ž×¨×” בהצלחה." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "מחק כתובת דו×״ל ×ישיות" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "הוסף כתובת דו×״ל ×ישיות" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "×ו תתחבר ×¢× ×ישיות!" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "×ו ×¨×©×•× ×ישיות חדשה!" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "× ×™×ª×Ÿ קובץ שגוי עבור טיפוס מדיה." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "העתקה ×ל ×חסון פומבי × ×›×©×œ×”." + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "קובץ עיבוד קביל ×œ× × ×ž×¦×" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "גודל קובץ מירבי {0} מ״ב" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "קובץ" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "ב×פשרותך להשתמש בתחביר\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> עבור עיצוב." + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "עליך לספק קובץ." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "הידד! × ×©×œ×—!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "×וסף \"%s\" התווסף!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "×תה חסו×." + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "×ª×ž×•× ×” של גובלין מת×מץ יתר על המידה" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "× ×סרת" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "עד %(until_when)s" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "לצמיתה" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "×מת ×ת הדו×״ל שלך!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "×”×ª× ×ª×§×•×ª" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "התחברות" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "החשבון של <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "×©× ×” הגדרות חשבון" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "לוח עיבוד מדיה" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "×”×ª× ×ª×§×•×ª" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "הוספת מדיה" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "צור ×וסף חדש" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "לוח × ×™×”×•×œ משתמש" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "לוח ×רגון דיווחי×" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "המדיות ×”××—×¨×•× ×•×ª ביותר" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "הרש××”" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "×שר" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "×תה מחובר בתור" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "×”×× ×‘×¨×¦×•× ×š להתיר " + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "ל×פליקציה ×œ× ×ž×•×›×¨×ª" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr " לגשת ×ל החשבון שלך? " + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "×פליקציות ×¢× ×’×™×©×” ×ל החשבון שלך מסוגלות: " + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "ר××” ×ת המידע שלך (למשל דיוקן, מדיה, וכו׳...)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "×©× ×” ×ת המידע שלך" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "הרש××” הסתיימה" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "הרש××” הושלמה" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "העתק והדבק ×ת מידע ×–×” ×ל תוך הלקוח שלך:" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "יצירת חשבון!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "צור" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "×©×œ×•× %(username)s,\n\nבכדי להפעיל ×ת ×—×©×‘×•× ×š בשירות GNU MediaGoblin, עליך לפתוח ×ת הכתובת הב××”\nבתוך דפדפן הרשת שלך:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." -msgstr "" +msgstr "×ž×ž×•× ×¢ על ידי <a href=\"http://mediagoblin.org/\" title='גירסה %(version)s'>MediaGoblin</a>, פרויקט <a href=\"http://gnu.org/\">GNU</a>." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -448,147 +920,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "משוחרר תחת הרשיון <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">קוד מקור</a> זמין." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "×ª×ž×•× ×” של גובלין מת×מץ יתר על המידה" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "×ª× ××™ שירות" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "לחקור" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "×©×œ×•× ×œ×š, ברוך בו×ך ×ל ×תר MediaGoblin ×–×”!" +msgstr "שלו×, ברוך בו×ך ×ל ×תר MediaGoblin ×–×”!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 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:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." -msgstr "בכדי להוסיף ×ת המדיה שלך, ×œ×”×©×™× ×ª×’×•×‘×•×ª, ועוד, ביכולתך להתחבר ×¢× ×—×©×‘×•×Ÿ MediaGoblin." +msgstr "בכדי להוסיף ×ת המדיה שלך, ×œ×¤×¨×¡× ×ª×’×•×‘×•×ª, ועוד, ב×פשרותך להתחבר ×¢× ×—×©×‘×•×Ÿ MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "×ין ברשותך חשבון עדיין? ×–×” קל!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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:47 -msgid "Most recent media" -msgstr "המדיה ×”××—×¨×•× ×” ביותר" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "×›×ן ביכולתך לעקוב ×חר המצב של המדיה שמתעבדת בשרת ×–×”." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "מדיה ב×מצע-עיבוד" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "×ין מדיה ב×מצע-עיבוד" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "העל×ות ×לה × ×›×©×œ×• להתעבד:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "×ין רשומות כושלות!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "10 העל×ות מוצלחות ××—×¨×•× ×•×ª" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "×ין ×¨×™×©×•×ž×™× ×ž×¢×•×‘×“×™×, עדיין!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "הגדר ×ת סיסמתך החדשה" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "הגדר סיסמה" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "שחזר סיסמה" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "שלח הור×ות" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" "\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "×©×œ×•× %(username)s,\n\nבכדי ×œ×©× ×•×ª ×ת סיסמתך ×צל GNU MediaGoblin, עליך לפתוח ×ת הכתובת הב××” \nבתוך דפדפן הרשת שלך:\n\n%(verification_url)s\n\nבמידה ו×תה חושב שמדובר בשגי××”, פשוט ×”×ª×¢×œ× ×ž×Ÿ דו×״ל ×–×” והמשך להיות\nגובלין מ×ושר!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "התחברות × ×›×©×œ×”!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "×ין לך חשבון עדיין?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "צור חשבון ×›×ן!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "שכחת ×ת סיסמתך?" +" >Create an account at this site</a>\n" +" or" +msgstr "\n >צור חשבון חדש ב×תר ×–×”</a>\n ×ו" -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "יצירת חשבון!" - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "יצירה" - -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" -"\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" "\n" -"%(verification_url)s" -msgstr "×©×œ×•× %(username)s,\n\nבכדי להפעיל ×ת ×—×©×‘×•× ×š ×צל GNU MediaGoblin, עליך לפתוח ×ת הכתובת הב××”\nבתוך דפדפן הרשת שלך:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">התקן MediaGoblin על השרת שלך</a>" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -602,13 +973,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "עריכת ×ª×¦×¨×™×¤×™× ×¢×‘×•×¨ %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "תצריפי×" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "הוספת תצריף" @@ -625,23 +996,29 @@ msgstr "ביטול" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "שמור ×©×™× ×•×™×™×" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "×©×™× ×•×™ דו×״ל של %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" -msgstr "" +msgstr "ב×מת למחוק ×ת המשתמש '%(user_name)s' ו×ת כל המדיה/התגובות הקשורות?" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 msgid "Yes, really delete my account" -msgstr "" +msgstr "כן, ב×מת למחוק ×ת ×—×©×‘×•× ×™" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "מחק לצמיתות" @@ -658,9 +1035,13 @@ msgstr "ערוך %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "×©×™× ×•×™ הגדרות חשבון עבור %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" -msgstr "" +msgstr "מחק ×ת החשבון שלי" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "דו×״ל" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format @@ -673,6 +1054,39 @@ msgstr "עריכת %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "עריכת דיוקן עבור %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "שלו×,\n\n×‘×¨×¦×•× × ×• ל×מת ×›×™ ×”×™× ×š %(username)s. ×× ×›×›×” ×כן, עליך \nלעקוב ×חר הקישור מטה כדי ל×מת ×ת כתובת הדו×״ל שלך.\n\n%(verification_url)s\n\n×× ××™× ×š %(username)s ×ו ×œ× ×‘×™×§×©×ª ×©×™× ×•×™ דו×״ל, ×פשר להתעל×\nמהודעת דו×״ל זו." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "תגובות חדשות" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "×œ×¤× ×™ %(formatted_time)s" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "סמן הכל ×›× ×§×¨×" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -683,8 +1097,8 @@ msgstr "מדיה מתויגת ×¢×: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "הורד" @@ -697,17 +1111,18 @@ msgid "" "Sorry, this audio will not work because \n" "\tyour web browser does not support HTML5 \n" "\taudio." -msgstr "צר לי, ×ודיו ×–×” ×œ× ×™×¢×‘×•×“ מכיוון \n\tשדפדפן הרשת שלך ×œ× ×ª×•×ž×š \n\t×ודיו של HTML5." +msgstr "×œ×¦×¢×¨× ×•, ×ודיו ×–×” ×œ× ×™×¢×‘×•×“ מכיוון \n\tשדפדפן הרשת שלך ×œ× ×ª×•×ž×š \n\t×ודיו של HTML5." #: mediagoblin/templates/mediagoblin/media_displays/audio.html:47 msgid "" "You can get a modern web browser that \n" "\tcan play the audio at <a href=\"http://getfirefox.com\">\n" "\t http://getfirefox.com</a>!" -msgstr "ביכולתך להשיג דפדפן רשת ×ž×•×“×¨× ×™ שכן \n\tמסוגל ×œ× ×’×Ÿ ×ת ×ודיו ×–×” ×צל <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" +msgstr "ב×פשרותך להשיג דפדפן רשת ×ž×•×“×¨× ×™ \n\tשכן מסוגל ×œ× ×’×Ÿ ×ת ×ודיו ×–×” ב×תר <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "קובץ מקורי" @@ -715,6 +1130,11 @@ msgstr "קובץ מקורי" msgid "WebM file (Vorbis codec)" msgstr "קובץ WebM (קודק Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "× ×•×¦×¨" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,70 +1145,395 @@ msgstr "קובץ WebM (קודק Vorbis)" msgid "Image for %(media_title)s" msgstr "×ª×ž×•× ×” עבור %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "קובץ PDF" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "× ×§×•×“×ª מבט" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "×œ×¤× ×™×" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "ר×ש" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "צד" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" -msgstr "" +msgstr "הורד מודל" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "פורמט קובץ" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "גובה ×ובייקט" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." -msgstr "" +msgstr "×œ×¦×¢×¨× ×•, ויד×ו ×–×” ×œ× ×™×¢×‘×•×“ מכיוון \n שדפדפן הרשת שלך ×œ× ×ª×•×ž×š \n ויד×ו של HTML5." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" -msgstr "" +msgstr "ב×פשרותך להשיג דפדפן רשת ×ž×•×“×¨× ×™ \n שכן מסוגל ×œ× ×’×Ÿ ×ת ויד×ו ×–×” ב×תר <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "קובץ WebM ‏(VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "×›×ן ב×פשרותך לעקוב ×חר המצב של המדיה שמתעבדת בשרת ×–×”." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "מדיה ב×מצע-עיבוד" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "×ין מדיה ב×מצע-עיבוד" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "העל×ות ×לה × ×›×©×œ×• להתעבד:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "×ין רשומות כושלות!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "10 העל×ות מוצלחות ××—×¨×•× ×•×ª" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "×ין ×¨×™×©×•×ž×™× ×ž×¢×•×‘×“×™×, עדיין!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "×œ×¦×¢×¨× ×•, ×œ× × ×ž×¦× ×“×™×•×•×— ×›×–×”." + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "חזור ×ל לוח דיווחי×" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "דווח" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "תגובה מדווחת" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "\n ■מדיה מדווחת של <a href=\"%(user_url)s\">%(user_name)s</a>\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "\n תוכן מ×ת\n <a href=\"%(user_url)s\"> %(user_name)s</a>\n × ×ž×—×§\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +#: mediagoblin/templates/mediagoblin/moderation/user.html:128 +msgid "Resolve" +msgstr "פתור" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "פתור ×ת דיווח ×–×”" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "סטטוס" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "× ×¤×ª×¨" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "×ין ב×פשרותך ×œ× ×§×•×˜ ב××ž×¦×¢×™× ×›× ×’×“ ×”×ž× ×”×œ×Ÿ" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "לוח דיווחי×" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "\n ×›×ן ב×פשרותך לבדוק ×“×™×•×•×—×™× ×¤×ª×•×—×™× ×שר מול×ו על ידי משתמשי×.\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "×“×™×•×•×—×™× ×¤×¢×™×œ×™× ×©× ×©×œ×—×•" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "מעליב" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "מתי דווח" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "דווח על ידי" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "סיבה" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "\n דיווח תגובה מספר %(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "\n דיווח מדיה מספר %(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "×œ× × ×ž×¦×ו ×“×™×•×•×—×™× ×¡×’×•×¨×™×." + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "×“×™×•×•×—×™× ×¡×’×•×¨×™×" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "× ×¤×ª×¨" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "פעולה ×©× × ×§×˜×”" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "קובץ WebM ‫(640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "\n דיווח סגור מספר %(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "×œ× × ×ž×¦×ו ×“×™×•×•×—×™× ×¡×’×•×¨×™×." + +#: mediagoblin/templates/mediagoblin/moderation/user.html:23 +#, python-format +msgid "User: %(username)s" +msgstr "משתמש: %(username)s" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:39 +msgid "Sorry, no such user found." +msgstr "×œ×¦×¢×¨× ×•, משתמש × ×ª×•×Ÿ ×œ× × ×ž×¦×." + +#: mediagoblin/templates/mediagoblin/moderation/user.html:43 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "× ×“×¨×© ×ימות דו×״ל" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:45 +msgid "" +"Someone has registered an account with this username, but it still has\n" +" to be activated." +msgstr "מישהו ×¨×©× ×—×©×‘×•×Ÿ ×¢× ×©× ×ž×©×ª×ž×© ×–×”, ×ך עליו\n לעבור ×קטיבציה." + +#: mediagoblin/templates/mediagoblin/moderation/user.html:58 +msgid "Return to Users Panel" +msgstr "חזור ×ל לוח משתמשי×" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:60 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 +#, python-format +msgid "%(username)s's profile" +msgstr "הדיוקן של %(username)s" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:62 +#, python-format +msgid "BANNED until %(expiration_date)s" +msgstr "×סור עד %(expiration_date)s" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:66 +msgid "Banned Indefinitely" +msgstr "×סור לצמיתות" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:72 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "משתמש ×–×” ×œ× ×ž×™×œ× ×“×™×•×§×Ÿ (עדיין)." + +#: mediagoblin/templates/mediagoblin/moderation/user.html:83 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "ערוך דיוקן" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:90 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "דפדוף ב×וספי×" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:97 +#, python-format +msgid "Active Reports on %(username)s" +msgstr "×“×™×•×•×—×™× ×¤×¢×™×œ×™× ×¢×œ %(username)s" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:104 +msgid "Report ID" +msgstr "מזהה (ID) דיווח" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:105 +msgid "Reported Content" +msgstr "תוכן מדווח" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:106 +msgid "Description of Report" +msgstr "תי×ור של דיווח" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:114 +#, python-format +msgid "Report #%(report_number)s" +msgstr "דיווח מספר %(report_number)s" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:121 +msgid "Reported Comment" +msgstr "תגובה מדווחת" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:123 +msgid "Reported Media Entry" +msgstr "ערך מדיה מדווח" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:134 +#, python-format +msgid "No active reports filed on %(username)s" +msgstr "×œ× × ×©×œ×—×• ×“×™×•×•×—×™× ×¤×¢×™×œ×™× ×¢×œ %(username)s" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:141 +#, python-format +msgid "All reports on %(username)s" +msgstr "כל ×”×“×™×•×•×—×™× ×¢×œ %(username)s" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:146 +#, python-format +msgid "All reports that %(username)s has filed" +msgstr "כל ×”×“×™×•×•×—×™× ×שר %(username)s שלח" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:160 +msgid "Ban User" +msgstr "×סור משתמש" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:165 +msgid "UnBan User" +msgstr "בטל הרחקת משתמש" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:173 +msgid "Privilege" +msgstr "פריבילגיה" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:174 +msgid "User Has Privilege" +msgstr "משתמש מחזיק בפריבילגיה" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:181 +msgid "Yes" +msgstr "כן" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:183 +msgid "No" +msgstr "ל×" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "לוח משתמש" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "\n ×›×ן ב×פשרותך לחפש ×ž×©×ª×ž×©×™× ×›×“×™ ×œ× ×§×•×˜ בפעולות ×¢×•× ×©×™×•×ª עליה×.\n " + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "×ž×©×ª×ž×©×™× ×¤×¢×™×œ×™×" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "מזהה" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "מתי הצטרף" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "מספר תגובות שפורסמו" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "×œ× × ×ž×¦×ו משתמשי×." #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "הוסף ×וסף" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "הוספת המדיה שלך" @@ -807,11 +1552,6 @@ msgstr "%(collection_title)s מ×ת <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "ערוך" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "מחק" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,19 +1563,19 @@ msgstr "ב×מת למחוק ×ת %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "ב×מת להסיר ×ת %(media_title)s מן %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "הסר" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 #, python-format msgid "%(username)s's collections" -msgstr "" +msgstr "×”××•×¡×¤×™× ×©×œ %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" -msgstr "" +msgstr "×”××•×¡×¤×™× ×©×œ <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -854,7 +1594,7 @@ msgstr "המדיה של %(username)s" msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "מדיה משתמש <a href=\"%(user_url)s\">%(username)s</a> ×¢× ×ª×’×™×ª <a href=\"%(tag_url)s\">%(tag)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -864,32 +1604,29 @@ msgstr "המדיה של <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/media.html:38 #, python-format msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" -msgstr "■עיון במדיה מ×ת <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "■דפדוף במדיה של <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "הוסף תגובה" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "הוסף ×ת תגובה זו" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "×צל" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "תצוגת תגובה" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>הוסף בת×ריך</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "התווספה" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 #, python-format msgid "Add “%(media_title)s†to a collection" -msgstr "" +msgstr "הוסף ×ת “%(media_title)s†×ל ×וסף" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" @@ -902,90 +1639,87 @@ msgstr "הוסף ×וסף חדש" #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29 msgid "" "You can track the state of media being processed for your gallery here." -msgstr "ביכולתך לעקוב ×›×ן ×חר מצב של מדיה שמצויה בתהליך עיבוד עבור הגלריה שלך." +msgstr "ב×פשרותך לעקוב ×חר מצב של מדיה שמצויה בתהליך עיבוד עבור הגלריה שלך ×›×ן." #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89 msgid "Your last 10 successful uploads" msgstr "10 ההעל×ות המוצלחות שלך" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "<h2>שליחת דיווח</h2>" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "דיווח על תגובה זו" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "דיווח על ערך מדיה ×–×”" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 #, python-format -msgid "%(username)s's profile" -msgstr "הדיוקן של %(username)s" +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "\n ■פורסמה על ידי <a href=\"%(user_url)s\"\n class=\"comment_authorlink\">%(username)s</a>\n " -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "צר לי, משתמש × ×ª×•×Ÿ ×œ× × ×ž×¦×." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "×ž×œ× ×“×™×•×•×—" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "× ×“×¨×© ×ימות דו×״ל" +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "×”× ×” ×ž×§×•× ×œ×•×ž×¨ ל××—×¨×™× ×ודותייך." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "צפיה בכל המדיה של %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "×›×ן ×–×” ×”×ž×§×•× ×‘×• המדיה שלך תופיע, ××•×œ× ×œ× × ×¨××” שהוספת משהו עדיין." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "×œ× × ×¨××” שיש ×›×ן מדיה כלשהי עדיין..." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 msgid "Almost done! Your account still needs to be activated." -msgstr "כמעת ×¡×™×™×ž× ×•! ×—×©×‘×•× ×š עדיין צריך ×קטיבציה." +msgstr "כמעת ×¡×™×™×ž× ×•! ×—×©×‘×•× ×š עדיין צריך לעבור ×קטיבציה." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "דו×״ל צפוי להגיע בעוד מספר ×¨×’×¢×™× ×‘×¦×™×¨×•×£ הור×ות ×‘× ×•×’×¢ לכיצד לעשות כך." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 msgid "In case it doesn't:" msgstr "במידה וזה ל×:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 msgid "Resend verification email" msgstr "שלח דו×״ל ×ימות" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." -msgstr "מישהו ×¨×©× ×—×©×‘×•×Ÿ ×¢× ×©× ×ž×©×ª×ž×© ×–×”, ×ך עליו להיות מופעל." +msgstr "מישהו ×¨×©× ×—×©×‘×•×Ÿ ×¢× ×©× ×ž×©×ª×ž×© ×–×”, ×ך עליו לעבור ×קטיבציה." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." -msgstr "×× ×תה ×כן ××“× ×–×” ××•×œ× ×יבדת ×ת דו×״ל ×”×ימות שלך, ביכולתך <a href=\"%(login_url)s\">להתחבר</a> ולשלוחו מחדש." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 -msgid "Here's a spot to tell others about yourself." -msgstr "×”× ×” ×ž×§×•× ×œ×•×ž×¨ ל××—×¨×™× ×ודותייך." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 -msgid "Edit profile" -msgstr "ערוך דיוקן" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 -msgid "This user hasn't filled in their profile (yet)." -msgstr "משתמש ×–×” ×œ× ×ž×™×œ× ×“×™×•×§×Ÿ (עדיין)." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 -msgid "Browse collections" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 -#, python-format -msgid "View all of %(username)s's media" -msgstr "צפיה בכל המדיה של %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 -msgid "" -"This is where your media will appear, but you don't seem to have added " -"anything yet." -msgstr "×›×ן ×–×” ×”×ž×§×•× ×‘×• המדיה שלך תופיע, ××•×œ× ×œ× × ×¨××” שהוספת משהו עדיין." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 -#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 -#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 -msgid "There doesn't seem to be any media here yet..." -msgstr "×œ× × ×¨××” שיש ×›×ן מדיה כלשהי עדיין..." +msgstr "×× ×ת/×” ×כן ××“× ×–×” ××•×œ× ×יבדת ×ת דו×״ל ×”×ימות שלך, ב×פשרותך <a href=\"%(login_url)s\">להתחבר</a> ולשלוחו מחדש." #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" @@ -993,11 +1727,11 @@ msgstr "(הסר)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" -msgstr "" +msgstr "× ×ספה בתוך" #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "הוסף ×ל ×וסף" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 @@ -1035,50 +1769,85 @@ msgstr "חדש יותר" msgid "older" msgstr "ישן יותר" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "דווח על מדיה" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "מתויגת ×¢×" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "×œ× ×”×™×” × ×™×ª×Ÿ ×œ×§×¨×•× ×ת קובץ ×”×ª×ž×•× ×”." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "×ופס!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "×ירעה שגי××”" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "בקשה רעה" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "הבקשה ×שר × ×©×œ×—×” ×ל השרת ×”×™× ×” שגויה, ×× × ×‘×—×Ÿ ×ותה היטב" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "פעולה ×œ× ×ž×•×¨×©×™×ª" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" -msgstr "צר לי דוד, ×× ×™ ×œ× ×™×›×•×œ להתיר לך לעשות ×–×ת!</p><p>× ×™×¡×™×ª לבצע פעולה ש××™× ×š מורשה לעשות. ×”×× × ×™×¡×™×ª למחוק ×ת כל ×”×—×©×‘×•× ×•×ª של ×”×ž×©×ª×ž×©×™× ×©×•×‘?" +msgstr "צר לי דייב, ×× ×™ ×œ× ×™×›×•×œ להתיר לך לעשות ×–×ת!</p><p>× ×™×¡×™×ª לבצע פעולה ש××™× ×š מורשה לעשות. ×”×× × ×™×¡×™×ª למחוק ×ת כל ×”×—×©×‘×•× ×•×ª של ×”×ž×©×ª×ž×©×™× ×©×•×‘?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." -msgstr "×œ× × ×¨××” ×©×§×™×™× ×¢×ž×•×“ בכתובת זו. צר לי!</p><p>×× ×תה בטוח שהכתובת ×”×™× ×” מדויקת, ייתכן שהעמוד ש×תה מחפש כעת הועבר ×ו × ×ž×—×§." +msgstr "×œ× × ×¨××” ×›×™ ×§×™×™× ×¢×ž×•×“ בכתובת זו. צר לי!</p><p>×× ×תה בטוח שהכתובת ×”×™× ×” מדויקת, ייתכן שהעמוד ש×תה מחפש כעת הועבר ×ו × ×ž×—×§." + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "×©× ×”" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "חודש" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "שבוע" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "יו×" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "שעה" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "דקה" #: mediagoblin/user_pages/forms.py:23 msgid "Comment" -msgstr "" +msgstr "תגובה" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "ביכולתך לעשות שימוש בתחביר <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> לעיצוב." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "ב×פשרותך להשתמש בתחביר <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Markdown</a> עבור עיצוב." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1090,7 +1859,7 @@ msgstr "×× ×™ בטוח ×©×‘×¨×¦×•× ×™ להסיר ×ת פריט ×–×” מן ×”×ו #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "×וסף" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" @@ -1100,73 +1869,84 @@ msgstr "-- בחר --" msgid "Include a note" msgstr "הכללת פתק" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "הגיב/×” על פרסומך" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "ב×פשרותך להשתמש בתחביר\n <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n Markdown</a> עבור עיצוב." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "סיבת דיווח" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "מצטערי×, תגובות ×ž× ×•×˜×¨×œ×•×ª." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "×ופס, תגובתך היתה ריקה." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "תגובתך פורסמה!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "×× × ×‘×“×•×§ ×ת רשומותיך ×•× ×¡×” שוב." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "עליך לבחור ×ו להוסיף ×וסף" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" כבר ×§×™×™× ×‘×וסף \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" -msgstr "\"%s\" התווסף ×ל ×”×וסף \"%s\"" +msgstr "\"%s\" התווספה ×ל ×”×וסף \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "מחקת ×ת מדיה זו." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "המדיה ×œ× × ×ž×—×§×” מכיוון ×©×œ× ×¡×™×ž× ×ª ש×תה בטוח." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "בחרת למחוק מדיה של משתמש ×חר. המשך בזהירות." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "מחקת ×ת הפריט מן ×וסף ×–×”." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "הפריט ×œ× ×”×•×¡×¨ מכיוון ×©×œ× ×¡×™×ž× ×ª ש×תה בטוח." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "בחרת למחוק פריט מן ×וסף של משתמש ×חר. המשך בזהירות." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "מחקת ×ת ×”×וסף \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "×”×וסף ×œ× ×”×•×¡×¨ מכיוון ×©×œ× ×¡×™×ž× ×ª ש×תה בטוח." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "בחרת למחוק ×וסף של משתמש ×חר. המשך בזהירות." diff --git a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo Binary files differindex d9addaa6..c8480c3e 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 73180e86..6c68ab33 100644 --- a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po @@ -3,16 +3,16 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Aleksandr Brezhnev <abrezhnev@gmail.com>, 2012. -# Emilio Sepúlveda <djfunkinmixer@gmail.com>, 2011. +# Aleksandr Brezhnev <abrezhnev@gmail.com>, 2012 +# Emilio Sepúlveda, 2011 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Interlingua (http://www.transifex.com/projects/p/mediagoblin/language/ia/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -20,253 +20,264 @@ msgstr "" "Language: ia\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Nomine de usator" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Contrasigno" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Adresse de e-posta" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." msgstr "" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "" -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "" - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titulo" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Etiquettas" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Sito web" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Contrasigno" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -274,15 +285,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Nomine de usator" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Adresse de e-posta" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "" @@ -292,6 +490,10 @@ msgstr "" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -346,7 +548,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -359,215 +561,327 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 -msgid "Invalid file given for media type." +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." msgstr "" -#: mediagoblin/submit/forms.py:26 -msgid "File" -msgstr "File" +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" -#: mediagoblin/submit/views.py:51 -msgid "You must provide a file." +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" msgstr "" -#: mediagoblin/submit/views.py:97 -msgid "Woohoo! Submitted!" +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/plugins/openid/views.py:106 #, python-format -msgid "Collection \"%s\" added!" +msgid "Verification of %s failed: %s" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 -msgid "Verify your email!" +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 -msgid "log out" +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 #: mediagoblin/templates/mediagoblin/auth/login.html:28 #: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 msgid "Log in" msgstr "Initiar session" -#: mediagoblin/templates/mediagoblin/base.html:79 -#, python-format -msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 -msgid "Change account settings" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 -msgid "Media processing panel" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 -msgid "Add media" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 -#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 -msgid "Create new collection" +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +"You can't delete your only Persona email address unless you have a password " +"set." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" msgstr "" +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "" + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "File" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "" + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 @@ -575,7 +889,7 @@ msgstr "" msgid "Create an account!" msgstr "Crear un conto!" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "" @@ -590,6 +904,62 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +972,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -625,12 +995,18 @@ msgstr "Cancellar" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -641,7 +1017,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "" @@ -658,10 +1034,14 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -673,6 +1053,39 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -683,8 +1096,8 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "" @@ -707,7 +1120,8 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -715,6 +1129,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,70 +1144,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "" @@ -807,11 +1423,6 @@ msgstr "" msgid "Edit" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,7 +1434,7 @@ msgstr "" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -866,23 +1477,20 @@ msgstr "" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -908,85 +1516,107 @@ msgstr "" msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Profilo de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "" +msgid "%(username)s's profile" +msgstr "Profilo de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "" +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1035,49 +1665,84 @@ msgstr "" msgid "older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1100,73 +1765,84 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mo Binary files differindex 376aace4..15366bcb 100644 --- a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po index 1b298a64..9c022469 100644 --- a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po @@ -3,15 +3,18 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <tryggvib@fsfi.is>, 2012. +# Sveinn à Felli <sveinki@nett.is>, 2013 +# tryggvib <tryggvib@fsfi.is>, 2012 +# tryggvib <tryggvib@fsfi.is>, 2013 +# tryggvib <tryggvib@fsfi.is>, 2012-2013 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Icelandic (Iceland) (http://www.transifex.com/projects/p/mediagoblin/language/is_IS/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,268 +22,466 @@ msgstr "" "Language: is_IS\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" - -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Þvà miður er nýskráning ekki leyfð á þessu svæði." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Notandanafn" +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "Þvà miður eru tilkynningar óvirkar á þessum vef." -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Lykilorð" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "Þvà miður er auðkenning ekki möguleg á þessu vefsvæði." -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Netfang" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "Ógilt notandanafn eða netfang" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Notandanafn eða netfang" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "Þessi reitur tekur ekki við netföngum." -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Þvà miður er nýskráning ekki leyfð á þessu svæði." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "à þennan reit verður að slá inn tölvupóstfang." -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Þvà miður er nú þegar til notandi með þetta nafn." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Þvà miður þá er annar notandi à kerfinu með þetta netfang skráð." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "Staðfestingarlykillinn eða notendaauðkennið er rangt." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Netfangið þitt hefur verið staðfest. Þú getur núna innskráð þig, breytt kenniskránni þinni og sent inn efni!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Staðfestingarlykillinn eða notendaauðkennið er rangt" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Þú verður að hafa innskráð þig svo við vitum hvert á að senda tölvupóstinn!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Þú hefur staðfest netfangið þitt!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Endursendi staðfestingartölvupóst" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Tölvupóstur hefur verið sendur með leiðbeiningum um hvernig þú átt að breyta lykilorðinu þÃnu." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Gat ekki sent tölvupóst um endurstillingu lykilorðs þvà notandanafnið þitt er óvirkt eða þá að þú hefur ekki staðfest netfangið þitt." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Þú getur núna innskráð þig með nýja lykilorðinu þÃnu." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titill" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Lýsing á þessu efni" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Þú getur notað\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> til að stÃlgera textann." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Efnisorð" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Aðskildu efnisorðin með kommum." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Vefslóðarormur" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "Vefslóðarormurinn getur ekki verið tómur" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Titilhlutinn à vefslóð þessa efnis. Þú þarft vanalega ekki að breyta þessu." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" -msgstr "Leyfi" +msgstr "Notkunarleyfi" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Lýsing" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "VefsÃða" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Þetta netfang inniheldur villur" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Gamla lykilorðið" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Skráðu gamla lykilorðið þitt til að sanna að þú átt þennan aðgang." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Senda mér tölvupóst þegar einhver bætir athugasemd við efnið mitt" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nýtt lykilorð" +msgid "Enable insite notifications about events." +msgstr "Virkja innri tilkynningar um viðburði." -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" -msgstr "" +msgstr "Stilling á notkunarleyfi" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" - -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Senda mér tölvupóst þegar einhver bætir athugasemd við efnið mitt" +msgstr "Þetta verður sjálfgefna leyfið þegar þú vilt hlaða upp efni." -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "Þessi titill getur verið innihaldslaus" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Lýsing á þessu albúmi" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "Titilhlutinn à vefslóð þessa albúms. Þú þarft vanalega ekki að breyta þessu." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Gamla lykilorðið" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Skráðu gamla lykilorðið þitt til að sanna að þú átt þennan aðgang." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nýtt lykilorð" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Nýtt netfang" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Lykilorð" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Sláðu inn lykilorðið þitt til að sanna að þú eigir þennan aðgang." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Efni merkt með þessum vefslóðarormi er nú þegar til fyrir þennan notanda." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Þú ert að breyta efni annars notanda. Farðu mjög varlega." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "Þú bættir við viðhenginu %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." -msgstr "" +msgstr "Þú getur bara breytt þinni eigin kenniskrá." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Þú ert að breyta kenniskrá notanda. Farðu mjög varlega." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Breytingar á kenniskrá vistaðar" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Vitlaust lykilorð" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Aðgangsstillingar vistaðar" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." -msgstr "" +msgstr "Þú verður að samþykkja eyðingu á notandaaðganginum þÃnum." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Þú hefur nú þegar albúm sem kallast \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "Albúm með þessu vefslóðarormi er nú þegar til fyrir þennan notanda." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Þú ert að breyta albúmi annars notanda. Farðu mjög varlega." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Netfangið þitt hefur verið staðfest." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Rangt lykilorð" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" -msgstr "Get ekki hlekkjað à þema... ekkert þema stillt\n" +msgstr "Get ekki tengt þema... ekkert þema stillt\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "Engin eignamappa fyrir þetta þema\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" -msgstr "Fann samt gamlan táknrænan tengil á möppu; fjarlægður.\n" +msgstr "Fann samt gamlan tákntengil á möppu; fjarlægður.\n" + +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "Gat ekki tengt \"%s\": %s er til og er ekki tákntengill\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "Hoppa yfir \"%s\"; hefur nú þegar verið sett upp.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "Gamall tengill fannst fyrir \"%s\"; fjarlægi.\n" #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.<br/>Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "CSRF smákaka ekki til staðar. Þetta er lÃklegast orsakað af smákökugildru eða einhverju þess háttar.<br/>Athugaðu hvort þú leyfir ekki alveg örugglega smákökur fyrir þetta lén." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Ég styð þvà miður ekki þessa gerð af skrám :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "tekst ekki að keyra unoconv, athugaðu annálsskrá" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" -msgstr "Myndbandsþverkótun mistókst" +msgstr "Þverkóðun myndskeiðs mistókst" + +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "Taka burt réttindi" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "Banna notanda" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "Senda notandanum skilaboð" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "Eyða efninu" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "Notandi à banni þangað til:" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "Af hverju ertu að banna þennan notanda?" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "Hvað ætlarðu að gera til að vinna úr tilkynningunni?" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "Hvaða réttindi ætlarðu að taka burt?" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "Viðvörun frá" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "skrifaði athugasemd við færsluna þÃna" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "Þú ert nú áskrifandi að athugasemdum „%s“!" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "Þú færð tilkynningar þegar einhver skrifar athugasemd við „%s“." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "Þú verður að gefa upp OAuth tóka (oauth_token)." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "Engin beiðni fannst." + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "Þvà miður er skráin of stór." + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "Þvà miður mun upphal á þessari skrá sprengja upphalshámarkið þitt." + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "Þvà miður hefur þú náð upphalshámarki" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Notandanafn" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Tölvupóstfang" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Notandanafn eða tölvupóstur" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "Muna eftir mér" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Notandanafn eða netfang" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Ef þetta netfang (há- og lágstafir skipta máli) er skráð hjá okkur hefur tölvupóstur verið sendur með leiðbeiningum um hvernig þú getur breytt lykilorðinu þÃnu." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Gat ekki fundið neinn með þetta notandanafn." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Tölvupóstur hefur verið sendur með leiðbeiningum um hvernig þú átt að breyta lykilorðinu þÃnu." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Gat ekki sent tölvupóst um endurstillingu lykilorðs þvà notandanafnið þitt er óvirkt eða þá að þú hefur ekki staðfest netfangið þitt." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "Notendaauðkennið er rangt." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Þú getur núna innskráð þig með nýja lykilorðinu þÃnu." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "Þú ert ekki lengur virkur notandi. Vinsamlegast talaðu við stjóranda til að endurvirkja aðganginn þinn." + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Það tókst að breyta lykilorðinu þÃnu" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Skrifaðu inn nýja lykilorðið þitt" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Skrá lykilorð" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Breyti lykilorði fyrir notandann: %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Vista" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Ertu ekki með notendaaðgang?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Búðu til aðgang hérna!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "Breyta lykilorðinu þÃnu." + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Endurstilla lykilorð" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Senda leiðbeiningar" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Gleymdirðu lykilorðinu þÃnu?" #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" @@ -291,6 +492,10 @@ msgstr "Staðsetning" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Skoða á <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "Skráðu þig inn til að búa til aðgang!" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Leyfa" @@ -301,7 +506,7 @@ msgstr "Banna" #: mediagoblin/plugins/oauth/forms.py:34 msgid "Name" -msgstr "Nafn" +msgstr "Heiti" #: mediagoblin/plugins/oauth/forms.py:35 msgid "The name of the OAuth client" @@ -345,236 +550,348 @@ msgstr "Ãframsendingarvefslóðin fyrir forritin, þessi reitur\n er msgid "This field is required for public clients" msgstr "Þessi reitur er nauðsynlegur fyrir opinbera biðlara" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Biðlarinn {0} hefur verið skráður!" #: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 msgid "OAuth client connections" -msgstr "" +msgstr "Biðlarartengingar OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "OAuth-biðlararnir þÃnir" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Bæta við" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "Þvà miður er annar aðgangur nú þegar skráður fyrir þetta OpenID auðkenni." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID auðkenni" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "Þvà miður fannst OpenID netþjónninn ekki" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "Engin OpenID þjónusta fannst fyrir „%s“" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Staðfesting á „%s“ mistóksts: „%s“" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Hætt við staðfestingu" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "Það tókst að vista OpenID vefslóðina þÃna." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "Þú getur ekki eytt einu OpenID vefslóðinni nema þú hafir skráð lykilorð" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "Þetta OpenID auðkenni er ekki skráð á þennan aðgang." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "Það tókst að fjarlægja OpenID auðkennið." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Bæta við OpenID auðkenni" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Eyða OpenID auðkenni" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Eyða" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "OpenID auðkenni" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Innskrá" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Mistókst að skrá þig inn." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "Skráðu þig inn til að búa til nýjan aðgang!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "...eða skráðu þig inn með lykilorði!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "...eða skráðu þig inn með OpenID auðkenni!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "...eða nýskráðu þig með OpenID auðkenni!" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "Þvà miður er annar aðgangur nú þegar skráður fyrir þetta „Persona“ netfang." + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "Það tókst að fjarlægja „Persona“ netfangið." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "Þú getur ekki eytt eina „Persona“ netfanginu þÃnu nema þú hafir skráð lykilorð." + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "Þetta „Persona“ netfang er ekki skráð fyrir þennan aðgang." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "Þvà miður er annar aðgangur nú þegar skráður fyrir þetta „Persona“ netfang." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Það tókst að vista „Persona“ netfangið þitt." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "Eyða „Persona“ netfangi" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "Bæta við „Persona“ netfangi" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "Persona auðkenni" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "...eða skráðu þig inn með „Persona“!" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "...eða nýskráðu þig með „Persona“!" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Ógild skrá gefin fyrir þessa margmiðlunartegund." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "Það tókst ekki að afrita yfir à almennu geymsluna." + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "Nothæf keyrsluskrá fannst ekki" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "Hámarksskráarstærð: {0} MB" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Skrá" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "Þú getur notað\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> fyrir stÃlsnið." + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Þú verður að gefa upp skrá." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Jibbà jei! Það tókst að senda inn!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "Albúmið \"%s\" var búið til!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "Þú ert à banni." + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Mynd af durt à stresskasti" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "Stjórnandi hefur bannað þig" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "þangað til %(until_when)s" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "ótilgreint" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Staðfestu netfangið þitt!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "útskrá" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Innskráning" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" -msgstr "Notandaaðgangur <a href=\"%(user_url)s\">%(user_name)s</a>" +msgstr "Notandaaðgangur: <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Breyta stillingum notandaaðgangs" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Margmiðlunarvinnsluskiki" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "Skrá út" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Senda inn efni" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Búa til nýtt albúm" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." -msgstr "Gefið út undir <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Frumkóti</a> aðgengilegur." +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "Notendastýring" -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "Mynd af durt à stresskasti" - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Skoða" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Hæ! Gakktu à bæinn á þetta MediaGoblin vefsvæði!" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "Tilkynningastýring" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." -msgstr "Þetta vefsvæði keyrira á <a href=\"http://mediagoblin.org\">MediaGoblin</a> sem er ótrúlega frábær hugbúnaður til að geyma margmiðlunarefni." - -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." -msgstr "Til að senda inn þitt efni, gera athugasemdir og fleira getur þú skráð þig inn með þÃnum MediaGoblin aðgangi." - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" -msgstr "Ertu ekki með aðgang? Það er auðvelt að búa til!" - -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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\">Búa til aðgang á þessari sÃðu</a>\n eða\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Settu upp þinn eigin margmiðlunarþjón</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Nýlegt efni" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Hér getur þú fylgst með margmiðlunarefni sem verið er að vinna á þessu vefsvæði." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Efni à vinnslu" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Heimilun" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Ekkert efni à vinnslu" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "Heimila" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Það mistókst að fullvinna þessar innsendingar:" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Þú ert" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Engar bilaðar innsendingar!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "Viltu heimila" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "SÃðustu 10 árangursrÃku innsendingarnar" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "óþekktu forriti" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Ekkert fullunnið efni enn!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Skrifaðu inn nýja lykilorðið þitt" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Skrá lykilorð" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "að fá aðgang að aðganginum þÃnum?" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Endurstilla lykilorð" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Forrit með aðgang að notendaaðganginum þÃnum geta:" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Senda leiðbeiningar" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "Sent inn nýtt margmiðlunarefni sem þú" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Hæ %(username)s,\n\ntil að breyta GNU MediaGoblin lykilorðinu þÃnu opnar þú eftirfarandi vefslóð à \nvafranum þÃnum:\n\n%(verification_url)s\n\nEf þú heldur að það sé einhver vitleysa à gangi husnar þú bara þennan póst og heldur áfram að vera\nánægður durtur!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "Skoða upplýsingarnar þÃnar (t.d. kenniskrá, margmiðlunarefni o.s.frv.)" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Mistókst að skrá þig inn." +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "Breytt upplýsingunum þÃnum" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Ertu ekki með notendaaðgang?" +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "Heimilun lokið" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Búðu til aðgang hérna!" +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "Heimild klár" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Gleymdirðu lykilorðinu þÃnu?" +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Afritaðu og lÃmdu þetta à forritið þitt:" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "Búðu til nýjan aðgang!" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "Búa til" @@ -589,6 +906,62 @@ msgid "" "%(verification_url)s" msgstr "Hæ %(username)s,\n\ntil að virkja GNU MediaGoblin aðganginn þinn, opnaðu þá eftirfarandi vefslóði Ã\nvafranum þÃnum:\n\n%(verification_url)s" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "Keyrt af <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, sem er <a href=\"http://gnu.org/\">GNU</a> verkefni." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "Gefið út undir <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Frumkóti</a> aðgengilegur." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "Notendaskilmálar" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Skoða" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Hæ! Gakktu à bæinn á þetta MediaGoblin vefsvæði!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "Þetta vefsvæði keyrir á <a href=\"http://mediagoblin.org\">MediaGoblin</a> sem er ótrúlega frábær hugbúnaður til að geyma margmiðlunarefni." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "Til að senda inn þitt efni, gera athugasemdir og fleira getur þú skráð þig inn með þÃnum MediaGoblin aðgangi." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "Ertu ekki með aðgang? Það er auðvelt að búa til!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "\n>Búa til aðgang á þessari sÃðu</a>\neða" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">settu upp þinn eigin margmiðlunarþjón</a>" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +974,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Breyti viðhengjum við: %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Viðhengi" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Bæta við viðhengi" @@ -624,23 +997,29 @@ msgstr "Hætta við" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Vista breytingar" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Breyti netfangi fyrir notandann: %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" -msgstr "" +msgstr "Virkilega eyða notanda '%(user_name)s' og tengt efni/athugasemdir?" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 msgid "Yes, really delete my account" -msgstr "" +msgstr "Já, ég vil örugglega eyða aðganginum mÃnum" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Eytt algjörlega" @@ -657,9 +1036,13 @@ msgstr "Breyti %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "Breyti notandaaðgangsstillingum fyrir: %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" -msgstr "" +msgstr "Eyða aðganginum mÃnum" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Netfang" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format @@ -672,6 +1055,39 @@ msgstr "Breyti %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Breyti kenniskrá notandans: %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "Hi,\n\nVið vildum staðfesta að þú værir notandinn „%(username)s“. Ef það er rétt,\nvinsamlegast smelltu á tengilinn hér fyrir neðan til að staðfesta nýja netfangið þitt.\n\n%(verification_url)s\n\nEf þú ert ekki „%(username)s“ or baðst ekki um að breytan netfanginu getur þú hunsað\nþennan tölvupóst." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Nýjar athugasemdir" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "Fyrir %(formatted_time)s" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Merkja allt lesið" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -682,10 +1098,10 @@ msgstr "Efni merkt með: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" -msgstr "Sækja af Netinu" +msgstr "Sækja" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38 msgid "Original" @@ -706,7 +1122,8 @@ msgid "" msgstr "Þú getur náð à nýlegan vafra sem \n\tgetur spilað hljóðskrár á <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Upphaflega skráin" @@ -714,6 +1131,11 @@ msgstr "Upphaflega skráin" msgid "WebM file (Vorbis codec)" msgstr "WebM skrá (Vorbis vÃxlþjöppun)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Búið til" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -724,70 +1146,267 @@ msgstr "WebM skrá (Vorbis vÃxlþjöppun)" msgid "Image for %(media_title)s" msgstr "Mynd fyrir %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "Stilla snúning af eða á" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF skrá" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" -msgstr "Sjónhorf" +msgstr "FjarvÃdd" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "Framhlið" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "Toppur" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "Hlið" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "Hala niður lÃkani" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "Skráarsnið" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "Hæð hlutar" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." -msgstr "" +msgstr "Þvà miður mun þetta myndskeið ekki virka þvÃ\n vafrinn þinn styður ekki HTML5 \n myndbönd." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" -msgstr "" +msgstr "Þú getur náð à nýlegan vafra sem \n sem getur spilað myndskeiðið á <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "WebM skrá (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Hér getur þú fylgst með margmiðlunarefni sem verið er að vinna á þessu vefsvæði." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Efni à vinnslu" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Ekkert efni à vinnslu" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Það mistókst að fullvinna þessar innsendingar:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Engar bilaðar innsendingar!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "SÃðustu 10 árangursrÃku innsendingarnar" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Ekkert fullunnið efni enn!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "Þvà miður fannst engin slÃk tilkynning." + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "Fara aftur à tilkynningastýringu" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "Tilkynning" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "Tilkynnt athugasemd" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "\n â– Tilkynnt efni sem <a href=\"%(user_url)s\">%(user_name)s</a> setti inn\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "\n EFNI SEM\n <a href=\"%(user_url)s\"> %(user_name)s</a>\n SETTI INN VAR EYTT\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "Leysa" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "Leysa þessa tilkynningu" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "Staða" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "LEYST" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "Þú getur ekki gert þetta gagnvart stjórnanda" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "Tilkynningastýring" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "\n Hér getur þú flett upp opnum tilkynningum frá notendum.\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "Virkar innsendar tilkynningar" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "Gerandi" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "Hvenær tilkynnt" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "Tilkynnt af" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "Ãstæða" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "\n Athugasemdartilkynning #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "\n Efnistilkynning #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "Engar opnar tilkynningar fundust." + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "Kláraðar tilkynningar" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "Leyst" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "Aðgerð tekin" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "\n Kláruð tilkynning #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "Engar kláraðar tilkynningar fundust." + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "Notendastýring" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "\n Hér getur þú skoðað notendur til að gera refsigaðgerðir gagnvart þeim.\n " + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "Virkir notendur" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "Auðkenni" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "Skráði sig" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "WebM skrá (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "Fjöldi athugasemda" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "Engir notendur fundust." #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Búa til albúm" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Sendu inn efni" @@ -806,11 +1425,6 @@ msgstr "%(collection_title)s sem <a href=\"%(user_url)s\">%(username)s</a> bjó msgid "Edit" msgstr "Breyta" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Eyða" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -822,19 +1436,19 @@ msgstr "Virkilega eyða %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Virkilega fjarlægja %(media_title)s úr %(collection_title)s albúminu?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Fjarlægja" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 #, python-format msgid "%(username)s's collections" -msgstr "" +msgstr "Albúm sem %(username)s á" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" -msgstr "" +msgstr "Albúm sem <a href=\"%(user_url)s\">%(username)s</a> á" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -853,7 +1467,7 @@ msgstr "Efni sem %(username)s á" msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "Efni sem <a href=\"%(user_url)s\">%(username)s</a> á og er merkt með <a href=\"%(tag_url)s\">%(tag)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -865,30 +1479,27 @@ msgstr "Efni sem <a href=\"%(user_url)s\">%(username)s</a> á" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Skoða efnið sem <a href=\"%(user_url)s\">%(username)s</a> setti inn" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Bæta við athugasemd" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Senda inn þessa athugasemd" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "hjá" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Útlit athugasemdar" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Bætt við:</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Bætt við" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 #, python-format msgid "Add “%(media_title)s†to a collection" -msgstr "" +msgstr "Setja '%(media_title)s' à albúm" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" @@ -907,96 +1518,118 @@ msgstr "Þú getur fylgst með hvernig gengur að vinna með margmiðlunarefnið msgid "Your last 10 successful uploads" msgstr "SÃðustu 10 árangursÃku innsendingarnar þÃnar" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "<h2>Senda inn tilkynningu</h2>" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "Tilkynni þessa athugasemd" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "Tilkynni þetta margmiðlunarefni" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "\n â– Höfundur: <a href=\"%(user_url)s\"\n class=\"comment_authorlink\">%(username)s</a>\n " + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "Tilkynna" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format msgid "%(username)s's profile" msgstr "Kenniskrá fyrir: %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Þvà miður fannst notandinn ekki." +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "Hér er svæði til að segja öðrum frá þér." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "Breyta kenniskrá" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "Þessi notandi hefur ekki fyllt inn à upplýsingar um sig (ennþá)." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "Skoða albúm" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "Skoða efnið sem %(username)s á" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "Þetta er staðurinn þar sem efnið þitt birtist en þú virðist ekki hafa sent neitt inn ennþá." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "Það virðist ekki vera neitt efni hérna ennþá..." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 msgid "Email verification needed" msgstr "Staðfesting á netfangi nauðsynleg" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 msgid "Almost done! Your account still needs to be activated." msgstr "Næstum þvà búið! Notandaaðgangurinn þinn verður að vera staðfestur." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "Tölvupóstur ætti að berast til þÃn eftir smástund með leiðbeiningum um hvernig þú átt að gera það." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 msgid "In case it doesn't:" msgstr "Ef það gerist ekki:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 msgid "Resend verification email" msgstr "Endursenda staðfestingarpóst" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "Einhver hefur búið til aðgang með þessu notandanafni en hefur ekki enn virkjað aðganginn." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." msgstr "Ef þú ert þessi aðili en hefur týnt staðfestingarpóstinum getur þú <a href=\"%(login_url)s\">skráð þig inn</a> og endursent hann" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 -msgid "Here's a spot to tell others about yourself." -msgstr "Hér er svæði til að segja öðrum frá þér." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 -msgid "Edit profile" -msgstr "Breyta kenniskrá" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 -msgid "This user hasn't filled in their profile (yet)." -msgstr "Þessi notandi hefur ekki fyllt inn à upplýsingar um sig (ennþá)." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 -msgid "Browse collections" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 -#, python-format -msgid "View all of %(username)s's media" -msgstr "Skoða efnið sem %(username)s á" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 -msgid "" -"This is where your media will appear, but you don't seem to have added " -"anything yet." -msgstr "Þetta er staðurinn þar sem efnið þitt birtist en þú virðist ekki hafa sent neitt inn ennþá." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 -#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 -#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 -msgid "There doesn't seem to be any media here yet..." -msgstr "Það virðist ekki vera neitt efni hérna ennþá..." - #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "(fjarlægja)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" -msgstr "" +msgstr "Sett à albúm" #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "Setja à albúm" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 @@ -1034,50 +1667,85 @@ msgstr "nýrri" msgid "older" msgstr "eldri" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "Tilkynna efni" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Merkt með" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Gat ekki lesið myndskrána." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "ObbosÃ!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Villa kom upp" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Ekki nógu góð beiðni" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "Beiðnin sem var send til netþjónsins er ógild, vinsamlegast athugaðu hana aftur" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "Aðgerð ekki leyfileg" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" -msgstr "Fyrirgefðu DavÃð. Ég get ekki leyft þér að gera þetta!</p></p>Þú hefur reynt að framkvæma aðger sem þú hefur ekki leyfi til. Varstu að reyna að eyða öllum notendunum aftur?" +msgstr "Fyrirgefðu DavÃð. Ég get ekki leyft þér að gera þetta!</p></p>Þú reyndir að framkvæma aðgerð sem þú hefur ekki leyfi til að gera. Varstu að reyna að eyða öllum notendareikningum aftur?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "Þvà miður! Það virðist ekki vera nein sÃða á þessari vefslóð.</p><p>Ef þú ert viss um að vefslóðin sé rétt hefur vefsÃðan sem þú ert að leita að kannski verið flutt eða fjarlægð." +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "ár" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "mánuður" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "vika" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "dagur" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "klukkustund" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "mÃnúta" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" -msgstr "" +msgstr "Athugasemd" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Þú getur notað <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> til að stÃlgera textann" +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Þú getur notað <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Markdown</a> til að stÃlgera textann." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1089,7 +1757,7 @@ msgstr "Ég er viss um að ég vilji fjarlægja þetta efni úr albúminu" #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "Albúm" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" @@ -1099,73 +1767,84 @@ msgstr "-- Velja --" msgid "Include a note" msgstr "Bæta við minnispunktum" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "skrifaði athugasemd við færsluna þÃna" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Þú getur notað\n <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n Markdown</a> til að stÃlgera textann." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "Ãstæður fyrir tilkynningu" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Þvà miður, athugasemdir eru óvirkar." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "ObbosÃ! Athugasemdin þÃn var innihaldslaus." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Athugasemdin þÃn var skráð!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." -msgstr "Vinsamlegast kÃktu á innsendingarnar þÃnar og reyndu aftur." +msgstr "Vinsamlegast kÃktu á færslurnar þÃnar og reyndu aftur." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Þú verður að velja eða búa til albúm" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" er nú þegar à albúminu \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" sett à albúmið \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Þú eyddir þessu efni." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "Efninu var ekki eytt þar sem þú merktir ekki við að þú værir viss." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Þú ert à þann mund að fara að eyða efni frá öðrum notanda. Farðu mjög varlega." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Þú tókst þetta efni úr albúminu." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "Þetta efni var ekki fjarlægt af þvà að þú merktir ekki við að þú værir viss." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Þú ert à þann mund að fara að eyða efni úr albúmi annars notanda. Farðu mjög varlega." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Þú eyddir albúminu \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "Þessu albúmi var ekki eytt vegna þess að þu merktir ekki við að þú værir viss." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Þú ert à þann mund að fara að eyða albúmi annars notanda. Farðu mjög varlega." diff --git a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo Binary files differindex 62451511..689a54b1 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 e13345a7..ca2605ba 100644 --- a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po @@ -3,18 +3,21 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Francesco Apruzzese <cescoap@gmail.com>, 2012. -# <pikappa469@alice.it>, 2011. -# <robi@nunnisoft.ch>, 2011. -# <sun_lion@live.com>, 2012. +# Damtux <sun_lion@live.com>, 2013 +# Francesco Apruzzese <cescoap@gmail.com>, 2012 +# gdb <gaedeb01@gmail.com>, 2013 +# pikappa469 <pikappa469@alice.it>, 2011 +# nunni <robi@nunnisoft.ch>, 2011 +# Damtux <sun_lion@live.com>, 2013 +# Damtux <sun_lion@live.com>, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Italian (http://www.transifex.com/projects/p/mediagoblin/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -22,269 +25,467 @@ msgstr "" "Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" - -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Spiacente, la registrazione è disabilitata su questa istanza." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Nome utente" +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "Spiacente, le segnalazioni sono disabilitate in questa istanza." -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Password" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "Mi dispiace, l'autenticazione è disabilitata in questa istanza." -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Indirizzo email" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "Nome utente o indirizzo email non valido." -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Nome utente o indirizzo email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "Questo campo non accetta indirizzi email." -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Spiacente, la registrazione è disabilitata su questa istanza." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "Questo campo richiede un indirizzo email." -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Spiacente, esiste già un utente con quel nome." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Siamo spiacenti, un utente con quell'indirizzo email esiste già ." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "La chiave di verifica o l'id utente è sbagliato." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Il tuo indirizzo email è stato verificato. Ora puoi accedere, modificare il tuo profilo e caricare immagini!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "La chiave di verifica o l'id utente è sbagliato" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Devi effettuare l'accesso così possiamo sapere a chi inviare l'email!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Hai già verificato il tuo indirizzo email!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Rispedisci email di verifica" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Ti è stata inviata un'email con le istruzioni per cambiare la tua password." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Impossibile inviare l'email di recupero password perchè il tuo nome utente è inattivo o il tuo indirizzo email non è stato verificato." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Ora puoi effettuare l'accesso con la nuova password." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titolo" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Descrizione di questo lavoro" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Puoi usare il\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> per la formattazione." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Tags" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." -msgstr "Separa le tags con la virgola." +msgstr "Separa i tag con la virgola." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" -msgstr "" +msgstr "Titolo" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" -msgstr "" +msgstr "Il titolo non può essere vuoto" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." -msgstr "Il titolo è parte dell'indirizzo del file. Nella maggior parte dei casi non c'è bisogno di cambiarlo." +msgstr "Il titolo fa parte dell'indirizzo del file. Nella maggior parte dei casi non c'è bisogno di cambiarlo." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Licenza" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Biografia" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Sito web" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Questo indirizzo contiene errori" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Password vecchia" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Inserisci la vecchia password per dimostrare di essere il proprietario dell'account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Inviami messaggi email quando altre persone commentano i miei file multimediali" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nuova password" +msgid "Enable insite notifications about events." +msgstr "Abilita le notifiche degli eventi nel sito." -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" -msgstr "" +msgstr "Licenza preferita" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" - -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Inviami messaggi email quando altre persone commentano i miei files multimediali" +msgstr "Questa sarà la tua licenza predefinita nei moduli di caricamento dei file." -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" -msgstr "" +msgstr "Il titolo non può essere vuoto" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" -msgstr "" +msgstr "Descrizione di questa raccolta" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." -msgstr "" +msgstr "Il titolo fa parte dell'indirizzo di questa raccolta. Nella maggior parte dei casi non c'è bisogno di cambiarlo." + +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Password vecchia" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Inserisci la vecchia password per dimostrare di essere il proprietario dell'account." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nuova password" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Nuovo indirizzo email" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Password" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Inserisci la tua password per dimostrare di essere il proprietario di questo account." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." -msgstr "" +msgstr "Questo utente ha già un elemento con quel titolo." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." -msgstr "Stai modificando files multimediali di un altro utente. Procedi con attenzione." +msgstr "Stai modificando file multimediali di un altro utente. Procedi con attenzione." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" -msgstr "" +msgstr "Hai aggiunto l'allegato %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." -msgstr "" +msgstr "Puoi modificare solo il tuo profilo." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Stai modificando il profilo di un utente. Procedi con attenzione." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Cambiamenti del profilo salvati" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Password errata" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Impostazioni del profilo salvate" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." -msgstr "" +msgstr "Devi confermare l'eliminazione del tuo account." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" -msgstr "" +msgstr "Hai già una raccolta che si chiama \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." -msgstr "" +msgstr "Questo utente ha già una raccolta con quel titolo." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." -msgstr "" +msgstr "Stai modificando la raccolta di un altro utente. Procedi con cautela." + +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Il tuo indirizzo email è stato verificato." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Password errata" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" -msgstr "" +msgstr "Non riesco a collegarmi al tema... nessun tema impostato\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.<br/>Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "Cookie CSRF non presente. Questo è dovuto a un plugin che blocca i cookie o a qualcosa del genere.<br/>Assicurati di permettere le impostazioni dei cookie per questo dominio." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Mi dispiace, non supporto questo tipo di file :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Transcodifica video fallita" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "Togli il privilegio" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "Banna l'utente" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "Invia un messaggio all'utente" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "Elimina il contenuto" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "L'utente verrà bannato fino al:" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "Perché stai bannando questo Utente?" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "Quali azioni intraprenderai per risolvere il problema?" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "Quali privilegi toglierai?" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "Avvertimento da parte di" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "ha commentato il tuo post" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "Devi specificare un oauth_token." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "Spiacente, il file è troppo grande." + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "Spiacente, caricando questo file supereresti il tuo limite di memoria." + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "Spiacente, hai raggiunto il limite di memoria disponibile." + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Nome utente" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Indirizzo email" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Nome utente o indirizzo Email" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "Rimani connesso" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Nome utente o indirizzo email" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Non ho trovato nessuno con quel nome utente." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Ti è stata inviata un'email con le istruzioni per cambiare la tua password." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Impossibile inviare l'email di recupero password perchè il tuo nome utente è inattivo o il tuo indirizzo email non è stato verificato." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "L'id utente è sbagliato." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Ora puoi effettuare l'accesso con la nuova password." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "Non sei più un utente attivo. Per favore contatta l'amministratore di sistema per riattivare il tuo account." + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "La tua password è stata cambiata con successo" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Imposta la nuova password" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Imposta password" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Stai cambiando la password di %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Salva" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Non hai ancora un account?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Creane uno qui!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "Cambia la tua password." + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Recupera Password" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Invia istruzioni" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Hai dimenticato la tua password?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Posizione" @@ -294,25 +495,29 @@ msgstr "Posizione" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Visualizza su <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "Iscriviti per creare un account!" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" -msgstr "" +msgstr "Consenti" #: mediagoblin/plugins/oauth/forms.py:30 msgid "Deny" -msgstr "" +msgstr "Nega" #: mediagoblin/plugins/oauth/forms.py:34 msgid "Name" -msgstr "" +msgstr "Nome" #: mediagoblin/plugins/oauth/forms.py:35 msgid "The name of the OAuth client" -msgstr "" +msgstr "Nome del client OAuth" #: mediagoblin/plugins/oauth/forms.py:36 msgid "Description" -msgstr "" +msgstr "Descrizione" #: mediagoblin/plugins/oauth/forms.py:38 msgid "" @@ -322,7 +527,7 @@ msgstr "" #: mediagoblin/plugins/oauth/forms.py:40 msgid "Type" -msgstr "" +msgstr "Tipo" #: mediagoblin/plugins/oauth/forms.py:45 msgid "" @@ -336,113 +541,382 @@ msgstr "" #: mediagoblin/plugins/oauth/forms.py:52 msgid "Redirect URI" -msgstr "" +msgstr "URI di Reindirizzamento" #: mediagoblin/plugins/oauth/forms.py:54 msgid "" "The redirect URI for the applications, this field\n" " is <strong>required</strong> for public clients." -msgstr "" +msgstr "L'URI di reindirizzamento per le applicazioni, questo campo\nè <strong>richiesto</strong> per i client pubblici." #: mediagoblin/plugins/oauth/forms.py:66 msgid "This field is required for public clients" -msgstr "" +msgstr "Questo campo è richiesto per i client pubblici" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" -msgstr "" +msgstr "Il client {0} è stato registrato!" #: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 msgid "OAuth client connections" -msgstr "" +msgstr "Connessioni client OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "I tuoi client OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Aggiungi" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "Mi dispiace, esiste già un account registrato con quell'OpenID." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "Mi dispiace, il server OpenID non è stato trovato" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "Nessun servizio OpenID è stato trovato per %s" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Verifica di %s fallita: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Verifica annullata" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "Il tuo url OpenID è stato salvato con successo." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "Non puoi eliminare il tuo unico URL OpenID se prima non hai impostato una password" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "Quell'OpenID non è registrato a questo account." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "OpenID è stato rimosso con successo." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Aggiungi un OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Elimina un OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Elimina" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "Gli OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Accedi" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Accesso fallito!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "Accedi per creare un account!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "O accedi con una password!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "O accedi con OpenID!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "O registrati con OpenID!" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "Mi dispiace, esiste già un account registrato con quell'indirizzo email Persona." + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "L'indirizzo email Persona è stato rimosso con successo." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "Non puoi eliminare il tuo unico indirizzo email Persona se prima non hai impostato una password." + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "Quell'indirizzo email Persona non è registrato in questo account." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "Mi dispiace, esiste già un account registrato con quell'indirizzo email Persona." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Il tuo indirizzo email Persona è stato salvato con successo." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "Elimina un indirizzo email Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "Aggiungi un indirizzo email Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "O accedi con Persona!" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "O registrati con Persona!" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "File non valido per il tipo di file multimediale indicato." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "Dimensione massima del file: {0} mb" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "File" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "Puoi utilizzare il\n<a href=\"http://daringfireball.net/projects/markdown/basics\">\nMarkdown</a> per la formattazione." + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Devi specificare un file." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Evviva! Caricato!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" +msgstr "Raccolta \"%s\" aggiunta!" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "Sei Bannato." + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "Sei stato bannato" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "fino al %(until_when)s" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "indefinitamente" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Verifica la tua email!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" -msgstr "" +msgstr "esci" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Accedi" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" -msgstr "" +msgstr "Account di <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Cambia le impostazioni dell'account" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" -msgstr "Pannello di elaborazione files multimediali" +msgstr "Pannello di elaborazione file multimediali" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "Esci" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" -msgstr "Aggiungi files multimediali" +msgstr "Aggiungi file multimediali" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" -msgstr "" +msgstr "Crea una nuova raccolta" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "Pannello di gestione degli utenti" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "Pannello di gestione delle segnalazioni" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "File multimediali più recenti" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Autorizzazione" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "Autorizza" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Sei connesso come" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "Vuoi autorizzare" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "un'applicazione sconosciuta" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "ad accedere al tuo account?" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Le applicazioni che accedono al tuo account possono:" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "Pubblica nuovi file multimediali a nome mio" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "Controlla le tue informazioni (ad es. il profilo, i file multimediali, ecc...)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "Cambiare le tue informazioni" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "Autorizzazione Finita" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "Autorizzazione Completata" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Copia e incolla questo nel tuo client:" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Crea un account!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Crea" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Ciao %(username)s,\n\nper attivare il tuo account GNU MediaGoblin, apri il seguente URL nel \ntuo navigatore web.\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." -msgstr "" +msgstr "Realizzato con <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, un progetto <a href=\"http://gnu.org/\">GNU</a>." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -450,147 +924,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Rilasciato con licenza <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Codice sorgente</a> disponibile." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "Termini di Servizio" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "Esplora" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Ciao, benvenuto in questo sito MediaGoblin!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 msgid "" "This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " "extraordinarily great piece of media hosting software." -msgstr "Questo sito sta utilizzando <a href=\"http://mediagoblin.org\">Mediagoblin</a>, un ottimo programma per caricare e condividere files multimediali." +msgstr "Questo sito sta utilizzando <a href=\"http://mediagoblin.org\">Mediagoblin</a>, un ottimo programma per caricare e condividere file multimediali." -#: mediagoblin/templates/mediagoblin/root.html:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Per aggiungere i tuoi file multimediali, scrivere commenti e altro puoi accedere con il tuo account MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "Non ne hai già uno? E' semplice!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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 un account in questo sito</a>\n oppure\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Installa MediaGoblin sul tuo server</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Files multimediali più recenti" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Qui è possibile tenere traccia dello stato dei file multimediali in fase di elaborazione in questa istanza." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Files multimediali in elaborazione" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Nessun file multimediale in elaborazione" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "L'elaborazione di questi files caricati è fallita:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "Ultimi 10 caricamenti riusciti" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Imposta la nuova password" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Imposta password" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Recupera Password" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Invia istruzioni" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" "\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Ciao %(username)s,\n\nper cambiare la tua password MediaGoblin apri il seguente URL nel\ntuo browser web:\n\n%(verification_url)s\n\nSe pensi che questo sia un errore, ignora semplicemente questa email e continua ad essere \nun goblin felice!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Accesso fallito!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Non hai ancora un account?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Creane uno qui!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Hai dimenticato la tua password?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Crea un account!" +" >Create an account at this site</a>\n" +" or" +msgstr "\n>Crea un account in questo sito</a>\noppure" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Crea" - -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" -"\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" "\n" -"%(verification_url)s" -msgstr "Ciao %(username)s,\n\nper attivare il tuo account GNU MediaGoblin, apri il seguente URL nel \ntuo navigatore web.\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n<a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Installa e configura MediaGoblin nel tuo server</a>" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -604,13 +977,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Stai modificando gli allegati di %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Allegati" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Aggiungi allegato" @@ -627,23 +1000,29 @@ msgstr "Annulla" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Salva i cambiamenti" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Stai cambiando l'email di %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" -msgstr "" +msgstr "Vuoi eliminare definitivamente l'utente '%(user_name)s' e tutti i file multimediali/commenti correlati?" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 msgid "Yes, really delete my account" -msgstr "" +msgstr "Sì, elimina definitivamente il mio account" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Elimina definitivamente" @@ -660,14 +1039,18 @@ msgstr "Stai modificando %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "Stai cambiando le impostazioni dell'account di %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" -msgstr "" +msgstr "Elimina il mio account" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Email" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" -msgstr "" +msgstr "Stai modificando %(collection_title)s" #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:34 @@ -675,18 +1058,51 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "Stai modificando il profilo di %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "Salve,\n\nVogliamo verificare che tu sia %(username)s. Se è così, allora \nper favore segui il link sottostante per verificare il tuo nuovo indirizzo email.\n\n%(verification_url)s\n\nSe tu non sei %(username)s oppure non hai richiesto un cambio dell'email, puoi ignorare questo messaggio." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Nuovi commenti" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)s fa" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Segna tutti come letti" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "File taggato con: %(tag_name)s" +msgstr "File taggati con: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Scarica" @@ -709,7 +1125,8 @@ msgid "" msgstr "Puoi scaricare un browser web moderno,\n\t in grado di leggere questo file audio, qui <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "File originario" @@ -717,6 +1134,11 @@ msgstr "File originario" msgid "WebM file (Vorbis codec)" msgstr "File WebM (codec Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Creato" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -727,93 +1149,285 @@ msgstr "File WebM (codec Vorbis)" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "File PDF" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" -msgstr "" +msgstr "Prospettiva" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" -msgstr "" +msgstr "Prospetto" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" -msgstr "" +msgstr "Pianta" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" -msgstr "" +msgstr "Lato" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" -msgstr "" +msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" -msgstr "" +msgstr "Scarica il modello" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" -msgstr "" +msgstr "Formato del File" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" -msgstr "" +msgstr "Altezza Oggetto" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." -msgstr "" +msgstr "Mi dispiace, questo video non funzionerà perché\n il tuo browser web non supporta i video in\n HTML5." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" +msgstr "Qui <a href=\"http://getfirefox.com\">http://getfirefox.com</a>\npuoi scaricare un browser web moderno, in grado di visualizzare\nquesto video!" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "File WebM (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Qui puoi seguire lo stato dei file multimediali in fase di elaborazione in questa istanza." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "File multimediali in elaborazione" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Nessun file multimediale in elaborazione" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "L'elaborazione di questi file caricati è fallita:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Nessuna elaborazione fallita!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Ultimi 10 caricamenti riusciti" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Finora nessun elemento elaborato!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "Spiacente, segnalazione non trovata." + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "Ritorna al Pannello Segnalazioni" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "Segnala" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "Commento segnalato" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "\nIL CONTENUTO DI\n<a href=\"%(user_url)s\"> %(user_name)s</a>\nÈ STATO ELIMINATO\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "Risolvi" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "Risolvi Questo Problema" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "Stato" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "RISOLTO" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "Non puoi agire contro un amministratore" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "File WebM (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "Colpevole" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "Segnalato Da" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "Motivazione" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "\nSegnalazione Commento #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "\nSegnalazione Elem. Multimediale #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "Segnalazioni Chiuse" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "Azione Intrapresa" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "\nSegnalazione Chiusa #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "Pannello utente" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "\nQui puoi cercare gli utenti per intraprendere azioni punitive nei loro confronti.\n " + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "Utenti Attivi" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "ID" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "# di Commenti Pubblicati" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "Nessun utente trovato." #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" -msgstr "" +msgstr "Aggiungi una raccolta" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Aggiungi il tuo file multimediale" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:30 #, python-format msgid "%(collection_title)s (%(username)s's collection)" -msgstr "" +msgstr "%(collection_title)s (raccolta di %(username)s)" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:39 #, python-format msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" -msgstr "" +msgstr "%(collection_title)s di <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:52 #: mediagoblin/templates/mediagoblin/user_pages/media.html:79 msgid "Edit" msgstr "Modifica" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Elimina" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,21 +1437,21 @@ msgstr "Vuoi davvero eliminare %(title)s?" #: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31 #, python-format msgid "Really remove %(media_title)s from %(collection_title)s?" -msgstr "" +msgstr "Eliminare definitivamente %(media_title)s da %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" -msgstr "" +msgstr "Elimina" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 #, python-format msgid "%(username)s's collections" -msgstr "" +msgstr "raccolte di %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" -msgstr "" +msgstr "raccolte di <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -849,157 +1463,176 @@ msgstr "Ciao %(username)s,\n%(comment_author)s ha commentato il tuo post (%(comm #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 #, python-format msgid "%(username)s's media" -msgstr "Files multimediali di %(username)s" +msgstr "File multimediali di %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38 #, python-format msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "File multimediali di <a href=\"%(user_url)s\">%(username)s</a> con tag <a href=\"%(tag_url)s\">%(tag)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" -msgstr "Files multimediali di <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "File multimediali di <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/media.html:38 #, python-format msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" -msgstr "â– Stai guardando i files multimediali di <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "â– Stai guardando i file multimediali di <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Aggiungi un commento" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Aggiungi questo commento" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "a" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Anteprima Commento" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Aggiunto il</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Aggiunto" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 #, python-format msgid "Add “%(media_title)s†to a collection" -msgstr "" +msgstr "Aggiungi “%(media_title)s†a una raccolta" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" -msgstr "" +msgstr "+" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58 msgid "Add a new collection" -msgstr "" +msgstr "Aggiungi una nuova raccolta" #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29 msgid "" "You can track the state of media being processed for your gallery here." -msgstr "Puoi controllare lo stato dei files multimediali in elaborazione per la tua galleria qui." +msgstr "Qui controlli lo stato dei file multimediali in elaborazione per la tua galleria." #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89 msgid "Your last 10 successful uploads" msgstr "I tuoi ultimi 10 caricamenti riusciti" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "profilo di %(username)s" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "<h2>Invia una Segnalazione</h2>" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Mi dispiace, utente non trovato." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "E' necessario verificare l'indirizzo email" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "Segnalare questo Commento" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Quasi finito! Il tuo account deve ancora essere attivato." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "Segnalare questo Elemento Multimediale" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "In breve dovresti ricevere un email contenente istruzioni su come fare." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Nel caso non fosse:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Rispedisci email di verifica" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "\nâ– Pubblicato da <a href=\"%(user_url)s\"\nclass=\"comment_authorlink\">%(username)s</a>\n " -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Qualcuno ha registrato un account con questo nome utente, ma deve ancora essere attivato." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Se sei quella persona ma hai perso l'email di verifica, puoi <a href=\"%(login_url)s\">accedere</a> e rispedirla." +msgid "%(username)s's profile" +msgstr "Profilo di %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Ecco un posto dove raccontare agli altri di te." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Modifica profilo" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Questo utente non ha (ancora) compilato il proprio profilo." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" -msgstr "" +msgstr "Sfoglia le raccolte" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" -msgstr "Visualizza tutti i files multimediali di %(username)s" +msgstr "Visualizza tutti i file multimediali di %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." -msgstr "Qui è dove appariranno i tuoi files multimediali, ma sembra che tu non abbia ancora aggiunto niente." +msgstr "I tuoi file multimediali appariranno qui, ma sembra che tu non abbia ancora aggiunto niente." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Sembra che non ci sia ancora nessun file multimediale qui..." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "E' necessario verificare l'indirizzo email" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Quasi finito! Il tuo account deve ancora essere attivato." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "In breve dovresti ricevere un email contenente istruzioni su come fare." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Nel caso non fosse:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Rispedisci email di verifica" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Qualcuno ha registrato un account con questo nome utente, ma deve ancora essere attivato." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Se sei quella persona ma hai perso l'email di verifica, puoi <a href=\"%(login_url)s\">accedere</a> e rispedirla." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" -msgstr "" +msgstr "(elimina)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" -msgstr "" +msgstr "Inserito in" #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "Aggiungi a una raccolta" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 @@ -1037,39 +1670,75 @@ msgstr "più recente" msgid "older" msgstr "più vecchio" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Taggato con" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Impossibile leggere il file immagine." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Oops!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" -msgstr "" +msgstr "Si è verificato un errore" + +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Richiesta Non Valida" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "La richiesta inviata al server non è valida, per favore ricontrolla" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" -msgstr "" +msgstr "Operazione non consentita" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" -msgstr "" +msgstr "Scusa Dave, non posso lasciartelo fare!</p><p>Hai cercato di eseguire una funzione non autorizzata. Stavi provando a eliminare di nuovo tutti gli account utente?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." -msgstr "" +msgstr "Mi dispiace! Sembra che non esista una pagina web con questo indirizzo.</p><p>Se ritieni che l'indirizzo sia corretto, forse la pagina che stai cercando è stata spostata o eliminata." + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "anno" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "mese" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "settimana" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "giorno" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "ora" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minuto" #: mediagoblin/user_pages/forms.py:23 msgid "Comment" @@ -1077,10 +1746,9 @@ msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Puoi usare il <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> per la formattazione." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Puoi usare il <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Markdown</a> per la formattazione." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1088,87 +1756,98 @@ msgstr "Sono sicuro di volerlo eliminare" #: mediagoblin/user_pages/forms.py:35 msgid "I am sure I want to remove this item from the collection" -msgstr "" +msgstr "Sono sicuro di voler eliminare questo elemento dalla raccolta" #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "Raccolta" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" -msgstr "" +msgstr "-- Seleziona --" #: mediagoblin/user_pages/forms.py:42 msgid "Include a note" -msgstr "" +msgstr "Includi una nota" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "ha commentato il tuo post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Puoi usare il\n<a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\nMarkdown</a> per la formattazione." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "Motivazione della Segnalazione" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Mi dispiace, i commenti sono disabilitati." + +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Oops, il tuo commento era vuoto." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Il tuo commento è stato aggiunto!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." -msgstr "" +msgstr "Per favore controlla i tuoi elementi e riprova." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" -msgstr "" +msgstr "Devi selezionare o aggiungere una raccolta" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" -msgstr "" +msgstr "\"%s\" è già nella raccolta \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" -msgstr "" +msgstr "\"%s\" aggiunto alla raccolta \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Hai eliminato il file." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "Il file non è stato eliminato perchè non hai confermato di essere sicuro." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Stai eliminando un file multimediale di un altro utente. Procedi con attenzione." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." -msgstr "" +msgstr "Hai eliminato l'elemento dalla raccolta." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." -msgstr "" +msgstr "L'elemento non è stato eliminato perchè non hai confermato di essere sicuro." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." -msgstr "" +msgstr "Stai eliminando un elemento dalla raccolta di un altro utente. Procedi con cautela." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" -msgstr "" +msgstr "Hai eliminato la raccolta \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." -msgstr "" +msgstr "La raccolta non è stata eliminata perchè non hai confermato di essere sicuro." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." -msgstr "" +msgstr "Stai eliminando la raccolta di un altro utente. Procedi con cautela." diff --git a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo Binary files differindex 1344c9bd..8c197dfd 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 008a6d27..a88cb020 100644 --- a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po @@ -3,16 +3,16 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <averym@gmail.com>, 2011. -# <parlegon@gmail.com>, 2013. +# Avery <averym@gmail.com>, 2011 +# parlegon <parlegon@gmail.com>, 2013 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Japanese (http://www.transifex.com/projects/p/mediagoblin/language/ja/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -20,253 +20,264 @@ msgstr "" "Language: ja\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ã“ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã§ç™»éŒ²ã¯ç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚" -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "ユーザãƒãƒ¼ãƒ " - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "パスワード" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "メールアドレス" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ã“ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã§ç™»éŒ²ã¯ç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚" +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ãã®åå‰ã‚’æŒã¤ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã™ã§ã«å˜åœ¨ã—ã¦ã„ã¾ã™ã€‚" -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "メアドãŒç¢ºèªã•れã¦ã„ã¾ã™ã€‚ã“れã§ã€ãƒã‚°ã‚¤ãƒ³ã—ã¦ãƒ—ãƒãƒ•ァイルを編集ã—ã€ç”»åƒã‚’æå‡ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ï¼" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "検証ã‚ーã¾ãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼IDãŒé–“é•ã£ã¦ã„ã¾ã™" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "検証メールをå†é€ã—ã¾ã—ãŸã€‚" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "" - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "タイトル" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "ã‚¿ã‚°" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "スラグ" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "スラグã¯å¿…è¦ã§ã™ã€‚" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "自己紹介" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "URL" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "パスワード" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "ãã®ã‚¹ãƒ©ã‚°ã‚’æŒã¤ã‚¨ãƒ³ãƒˆãƒªã¯ã€ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯æ—¢ã«å˜åœ¨ã—ã¾ã™ã€‚" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "ã‚ãªãŸã¯ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’編集ã—ã¦ã„ã¾ã™ã€‚ã”æ³¨æ„ãã ã•ã„。" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "ã‚ãªãŸã¯ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ãƒãƒ•ァイルを編集ã—ã¦ã„ã¾ã™ã€‚ã”æ³¨æ„ãã ã•ã„。" -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -274,15 +285,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "ユーザãƒãƒ¼ãƒ " + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "メールアドレス" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "ã¾ã アカウントをæŒã£ã¦ã„ã¾ã›ã‚“ã‹ï¼Ÿ" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "ã“ã“ã§ä½œæˆï¼" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "パスワードを忘れã¾ã—ãŸã‹ï¼Ÿ" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "" @@ -292,6 +490,10 @@ msgstr "" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -346,7 +548,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -359,223 +561,335 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "è¿½åŠ " -#: mediagoblin/processing/__init__.py:172 -msgid "Invalid file given for media type." +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." msgstr "" -#: mediagoblin/submit/forms.py:26 -msgid "File" -msgstr "ファイル" +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" -#: mediagoblin/submit/views.py:51 -msgid "You must provide a file." -msgstr "ファイルをæä¾›ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" -#: mediagoblin/submit/views.py:97 -msgid "Woohoo! Submitted!" -msgstr "投稿終了ï¼" +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/plugins/openid/views.py:106 #, python-format -msgid "Collection \"%s\" added!" +msgid "Verification of %s failed: %s" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 -msgid "Verify your email!" +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 -msgid "log out" +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "削除" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 #: mediagoblin/templates/mediagoblin/auth/login.html:28 #: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 msgid "Log in" msgstr "ãƒã‚°ã‚¤ãƒ³" -#: mediagoblin/templates/mediagoblin/base.html:79 -#, python-format -msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 -msgid "Change account settings" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 -msgid "Media processing panel" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 -msgid "Add media" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 -#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 -msgid "Create new collection" +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +"You can't delete your only Persona email address unless you have a password " +"set." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." msgstr "" +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "ファイル" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "ファイルをæä¾›ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "投稿終了ï¼" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "ã“ã‚“ã«ã¡ã¯ã€ã“ã®MediaGoblinサイトã¸ã‚ˆã†ã“ãï¼" +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "ã¾ã アカウントをæŒã£ã¦ã„ã¾ã›ã‚“ã‹ï¼Ÿ" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "ã“ã“ã§ä½œæˆï¼" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "パスワードを忘れã¾ã—ãŸã‹ï¼Ÿ" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "アカウントを作æˆï¼" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "" @@ -590,6 +904,62 @@ msgid "" "%(verification_url)s" msgstr "%(username)s様ã¸\n\nGNU MediaGoblinアカウントを検証ã«ã™ã‚‹ã«ã¯ã€ã“ã®URLã‚’é–‹ã„ã¦ãã ã•ã„。\n\n%(verification_url)s" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "ã“ã‚“ã«ã¡ã¯ã€ã“ã®MediaGoblinサイトã¸ã‚ˆã†ã“ãï¼" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +972,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -625,12 +995,18 @@ msgstr "ã‚ャンセル" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "投稿ã™ã‚‹" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -641,7 +1017,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "" @@ -658,10 +1034,14 @@ msgstr "%(media_title)sを編集ä¸" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -673,6 +1053,39 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "%(username)sã•ã‚“ã®ãƒ—ãƒãƒ•ィールを編集ä¸" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -683,8 +1096,8 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "ダウンãƒãƒ¼ãƒ‰" @@ -707,7 +1120,8 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -715,6 +1129,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,70 +1144,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "" @@ -807,11 +1423,6 @@ msgstr "" msgid "Edit" msgstr "編集" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "削除" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,7 +1434,7 @@ msgstr "" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -866,23 +1477,20 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>ã•ã‚“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -908,85 +1516,107 @@ msgstr "" msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)sã•ã‚“ã®ãƒ—ãƒãƒ•ィール" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "メールã¯ã€ãã®æ–¹æ³•ã®æŒ‡ç¤ºã§ã„ãã¤ã‹ã®çž¬é–“ã«åˆ°ç€ã—ã¾ã™ã€‚" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "到ç€ã—ãªã„å ´åˆã¯ã€" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "確èªãƒ¡ãƒ¼ãƒ«ã‚’å†é€ä¿¡" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "ã‚ãªãŸã®ç¢ºèªãƒ¡ãƒ¼ãƒ«ã‚’紛失ã—ãŸå ´åˆã€<a href=\"%(login_url)s\">ãƒã‚°ã‚¤ãƒ³</a>ã—ã¦å†é€ã§ãã¾ã™ã€‚" +msgid "%(username)s's profile" +msgstr "%(username)sã•ã‚“ã®ãƒ—ãƒãƒ•ィール" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "プãƒãƒ•ィールを編集" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "%(username)sã•ã‚“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’ã™ã¹ã¦è¦‹ã‚‹" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "" +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "メールã¯ã€ãã®æ–¹æ³•ã®æŒ‡ç¤ºã§ã„ãã¤ã‹ã®çž¬é–“ã«åˆ°ç€ã—ã¾ã™ã€‚" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "到ç€ã—ãªã„å ´åˆã¯ã€" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "確èªãƒ¡ãƒ¼ãƒ«ã‚’å†é€ä¿¡" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "ã‚ãªãŸã®ç¢ºèªãƒ¡ãƒ¼ãƒ«ã‚’紛失ã—ãŸå ´åˆã€<a href=\"%(login_url)s\">ãƒã‚°ã‚¤ãƒ³</a>ã—ã¦å†é€ã§ãã¾ã™ã€‚" + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1035,49 +1665,84 @@ msgstr "" msgid "older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1100,73 +1765,84 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mo Binary files differindex 69bf72bc..ce69f3f2 100644 --- a/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po index ac87c90f..6f1bd924 100644 --- a/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po @@ -3,15 +3,15 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <newvgund@gmail.com>, 2012. +# Jin-hoon Kim <newvgund@gmail.com>, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Korean (Korea) (http://www.transifex.com/projects/p/mediagoblin/language/ko_KR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,253 +19,264 @@ msgstr "" "Language: ko_KR\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "죄송합니다. ì§€ê¸ˆì€ ê°€ìž… 하실 수 없습니다." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "" -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "ì‚¬ìš©ìž ì´ë¦„" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "비밀번호" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "email 주소" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "ì‚¬ìš©ìž ì´ë¦„ ë˜ëŠ” email" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "죄송합니다. ì§€ê¸ˆì€ ê°€ìž… 하실 수 없습니다." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "죄송합니다. 해당 ì‚¬ìš©ìž ì´ë¦„ì´ ì´ë¯¸ 존재 합니다." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "죄송합니다. 사용ìžì™€ 해당 ì´ë©”ì¼ì€ ì´ë¯¸ 등ë¡ë˜ì–´ 있습니다." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "해당 email 주소가 ì´ë¯¸ ì¸ì¦ ë˜ì–´ 있습니다. 지금 로그ì¸í•˜ì‹œê³ ê³„ì • ì •ë³´ë¥¼ ìˆ˜ì •í•˜ê³ ì‚¬ì§„ì„ ì „ì†¡í•´ 보세요!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "ì¸ì¦ 키 ë˜ëŠ” ì‚¬ìš©ìž IDê°€ 올바르지 않습니다." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "로그ì¸ì„ 하셔야 ê³ ë¸”ë¦°ì—서 ë©”ì¼ì„ 보낼 수 있습니다!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "ì´ë¯¸ ì¸ì¦ë°›ì€ email 주소를 ê°€ì§€ê³ ìžˆìŠµë‹ˆë‹¤!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "ì¸ì¦ ë©”ì¼ì„ 다시 ë³´ë‚´ 주세요." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "비밀번호를 변경하는 ë°©ë²•ì— ëŒ€í•œ 설명서가 ë©”ì¼ë¡œ ì „ì†¡ ë˜ì—ˆìŠµë‹ˆë‹¤." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "사용ìžì˜ ì´ë¦„ì´ ì¡´ìž¬í•˜ì§€ 않거나, 사용ìžì˜ email 주소가 ì¸ì¦ë˜ì§€ 않아 비밀번호 복구 ë©”ì¼ì„ 보낼 수 없습니다." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "ì´ì œ 새로운 비밀번호로 ë¡œê·¸ì¸ í•˜ì‹¤ 수 있습니다." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "ì œëª©" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "ì´ ìž‘ì—…ì— ëŒ€í•œ 설명" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "í¬ë©§íŒ…ì„ ì‚¬ìš©í•˜ë ¤ë©´\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> ë§í¬ë¥¼ ì°¸ê³ í•˜ì„¸ìš”." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "태그" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "태그는 , 로 구분 ë©ë‹ˆë‹¤." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "'슬러그'" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "'슬러그'는 ê³µë°±ì¼ ìˆ˜ 없습니다." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "ì œëª©ì€ ë¯¸ë””ì–´ ì£¼ì†Œì˜ ì¼ë¶€ë¶„ 입니다. ìˆ˜ì •í•˜ì§€ ì•Šì•„ë„ ë©ë‹ˆë‹¤." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "License" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "소개" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "웹 주소" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "ì£¼ì†Œì— ì—러가 있습니다." -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "ì˜ˆì „ 비밀번호" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "ê³„ì • 확ì¸ì„ 위해, ì´ì „ 비밀 번호를 ìž…ë ¥í•´ 주세요." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "ì œ ë¯¸ë””ì–´ì— ëŒ€í•œ 컨í…ì„ ì›í•œë‹¤ë©´, ë©”ì¼ì„ 보내주세요." #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "새로운 비밀번호" +msgid "Enable insite notifications about events." +msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "ì œ ë¯¸ë””ì–´ì— ëŒ€í•œ 컨í…ì„ ì›í•œë‹¤ë©´, ë©”ì¼ì„ 보내주세요." - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "ì œëª©ì€ ê³µë°±ì¼ ìˆ˜ 없습니다." -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "모ìŒì§‘ì— ëŒ€í•œ 설명" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "ì˜ˆì „ 비밀번호" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "ê³„ì • 확ì¸ì„ 위해, ì´ì „ 비밀 번호를 ìž…ë ¥í•´ 주세요." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "새로운 비밀번호" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "비밀번호" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "해당 ìœ ì €ì— ëŒ€í•œ '슬러그'ê°€ ì´ë¯¸ 존재합니다." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "다른 사용ìžì˜ 미디어를 ìˆ˜ì •í•˜ê³ ìžˆìŠµë‹ˆë‹¤. 조심해서 ìˆ˜ì •í•˜ì„¸ìš”." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "사용ìžì˜ ê³„ì • ì •ë³´ë¥¼ ìˆ˜ì •í•˜ê³ ìžˆìŠµë‹ˆë‹¤. 조심해서 ìˆ˜ì •í•˜ì„¸ìš”." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "ê³„ì • ì •ë³´ê°€ ì €ìž¥ ë˜ì—ˆìŠµë‹ˆë‹¤." -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "ìž˜ëª»ëœ ë¹„ë°€ë²ˆí˜¸" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "ê³„ì • ì„¤ì •ì´ ì €ìž¥ ë˜ì—ˆìŠµë‹ˆë‹¤." -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "\"%s\" 모ìŒì§‘ì„ ì´ë¯¸ ê°€ì§€ê³ ìžˆìŠµë‹ˆë‹¤!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "다른 ìœ ì €ì˜ ëª¨ìŒì§‘ì„ ìˆ˜ì • 중 입니다. 주ì˜í•˜ì„¸ìš”." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "ìž˜ëª»ëœ ë¹„ë°€ë²ˆí˜¸" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "í…Œë§ˆì— ì—°ê²°í• ìˆ˜ 없습니다... 테마 ì…‹ì´ ì—†ìŠµë‹ˆë‹¤.\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "ì´ í…Œë§ˆë¥¼ 위한 ì—ì…‹ ë””ë ‰í† ë¦¬ê°€ 없습니다.\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "그런ë°, ì˜¤ëž˜ëœ ë””ë ‰í† ë¦¬ ì‹¬ë³¼ë¦ ë§í¬ë¥¼ 찾았습니다; 지워졌습니다.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -273,15 +284,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "죄송합니다. 해당 íƒ€ìž…ì˜ íŒŒì¼ì€ ì§€ì›í•˜ì§€ 않아요 :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "비디오 ë³€í™˜ì— ì‹¤íŒ¨ 했습니다." +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "ê²Œì‹œë¬¼ì— ë§ê¸€ì´ ë‹¬ë ¸ìŠµë‹ˆë‹¤." + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "ì‚¬ìš©ìž ì´ë¦„" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "email 주소" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "ì‚¬ìš©ìž ì´ë¦„ ë˜ëŠ” email" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "비밀번호를 변경하는 ë°©ë²•ì— ëŒ€í•œ 설명서가 ë©”ì¼ë¡œ ì „ì†¡ ë˜ì—ˆìŠµë‹ˆë‹¤." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "사용ìžì˜ ì´ë¦„ì´ ì¡´ìž¬í•˜ì§€ 않거나, 사용ìžì˜ email 주소가 ì¸ì¦ë˜ì§€ 않아 비밀번호 복구 ë©”ì¼ì„ 보낼 수 없습니다." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "ì´ì œ 새로운 비밀번호로 ë¡œê·¸ì¸ í•˜ì‹¤ 수 있습니다." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "새로운 비밀번호를 ì„¤ì • 하세요." + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "비밀번호 ì„¤ì •" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "ì•„ì§ ê³„ì •ì´ ì—†ìœ¼ì„¸ìš”?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "ì´ê³³ì—서 새로 만드세요!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "비밀번호 복구" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "설명서 보내기" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "비밀번호를 잊으셨나요?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "장소" @@ -291,6 +489,10 @@ msgstr "장소" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr " <a href=\"%(osm_url)s\">OpenStreetMap</a>으로 보기" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "허용" @@ -345,7 +547,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "ì´ í•ëª©ì€ ê³µê°œ 사용ìžë“¤ì„ 위해 ê¼ í•„ìš” 합니다." -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "ì‚¬ìš©ìž {0}ë‹˜ì´ ë“±ë¡ ë˜ì—ˆìŠµë‹ˆë‹¤!" @@ -358,223 +560,335 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "추가" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "ì‚ì œ" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "로그ì¸" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "로그ì¸ì— 실패 했습니다!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "알수없는 미디어 íŒŒì¼ ìž…ë‹ˆë‹¤." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "파ì¼" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "파ì¼ì„ 등ë¡í•˜ì…”야 합니다." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "ì´í–!! 등ë¡í–ˆìŠµë‹ˆë‹¤!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "\"%s\" 모ìŒì§‘ì´ ì¶”ê°€ë˜ì—ˆìŠµë‹ˆë‹¤!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "ë©”ì¼ì„ 확ì¸í•˜ì„¸ìš”!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "로그ì¸" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "ê³„ì • ì„¤ì • 변경" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "미디어 작업 패ë„" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "미디어 추가" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." -msgstr "Released under the <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Source code</a> available." - -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "íƒìƒ‰" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "안녕하세요! 미디어 ê³ ë¸”ë¦° 사ì´íŠ¸ì— ì˜¨ê±¸ í™˜ì˜ í•©ë‹ˆë‹¤!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -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:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." -msgstr "ìžì‹ ì˜ ë¯¸ë””ì–´ë¥¼ ì¶”ê°€í•˜ê³ , ëŒ“ê¸€ì„ ë‚¨ê¸°ì„¸ìš”! 미디어 ê³ ë¸”ë¦° ê³„ì •ìœ¼ë¡œ ë‚´ì—ì„ í™•ì¸ í•˜ì‹¤ 수 있습니다!" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" -msgstr "ì•„ì§ ì•„ë¬´ê²ƒë„ ì—†ìœ¼ì‹œë‹¤êµ¬ìš”? 매우 쉽습니다!" - -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "가장 ìµœê·¼ì— ë“±ë¡ëœ 미디어" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "미디어 작업중..." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "ìž‘ì—…ì¤‘ì¸ ë¯¸ë””ì–´ê°€ 없습니다." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "ë‹¤ìŒ ìž‘ì—…ì„ í•˜ëŠ” ì¤‘ì— ì—…ë¡œë“œì— ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤.:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "지난 10ê°œì˜ ì—…ë¡œë“œ 목ë¡" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "새로운 비밀번호를 ì„¤ì • 하세요." +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "비밀번호 ì„¤ì •" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "비밀번호 복구" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "설명서 보내기" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "안녕하세요 %(username)s,\n\nGNU MediaGoblinì˜ ì‚¬ìš©ìž ê³„ì • 비밀번호를 ë°”ê¾¸ì‹œë ¤ë©´, ì¸í„°ë„· ì°½ì„ ì—¬ì‹œê³ ì•„ëž˜ URLì„ í†µí•´ ì ‘ì† í•˜ì„¸ìš”. :\n\n%(verification_url)s\n\n오류ë¼ê³ ìƒê° ëœë‹¤ë©´, ì´ ë©”ì¼ì„ ë¬´ì‹œí•˜ì‹œê³ ê³ ë¸”ë¦°ì„ ì¦ê¸°ì„¸ìš”!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "로그ì¸ì— 실패 했습니다!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "ì•„ì§ ê³„ì •ì´ ì—†ìœ¼ì„¸ìš”?" +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "ì´ê³³ì—서 새로 만드세요!" +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "비밀번호를 잊으셨나요?" +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "ê³„ì •ì„ ìƒˆë¡œ ë§Œë“니다!" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "ìƒì„±" @@ -589,6 +903,62 @@ msgid "" "%(verification_url)s" msgstr "안녕하세요 %(username)s님,\n\nGNU MediaGoblin ê³„ì •ì„ í™œì„±í™” í•˜ì‹œë ¤ë©´, ì•„ëž˜ì˜ URL 주소를 브ë¼ìš°ì ¸ë¡œ ì ‘ì†í•˜ì„¸ìš”.\n\n%(verification_url)s" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "Released under the <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Source code</a> available." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "íƒìƒ‰" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "안녕하세요! 미디어 ê³ ë¸”ë¦° 사ì´íŠ¸ì— ì˜¨ê±¸ í™˜ì˜ í•©ë‹ˆë‹¤!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +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/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "ìžì‹ ì˜ ë¯¸ë””ì–´ë¥¼ ì¶”ê°€í•˜ê³ , ëŒ“ê¸€ì„ ë‚¨ê¸°ì„¸ìš”! 미디어 ê³ ë¸”ë¦° ê³„ì •ìœ¼ë¡œ ë‚´ì—ì„ í™•ì¸ í•˜ì‹¤ 수 있습니다!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "ì•„ì§ ì•„ë¬´ê²ƒë„ ì—†ìœ¼ì‹œë‹¤êµ¬ìš”? 매우 쉽습니다!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +971,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "%(media_title)sì˜ ì²¨ë¶€ ìˆ˜ì • 중..." #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "첨부" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "첨부 추가" @@ -624,12 +994,18 @@ msgstr "취소" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "ì €ìž¥" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -640,7 +1016,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "ì˜êµ¬ì 으로 ì‚ì œ" @@ -657,10 +1033,14 @@ msgstr "%(media_title)s 편집중..." msgid "Changing %(username)s's account settings" msgstr "%(username)s'ì˜ ê³„ì • ì„¤ì • 변경중..." -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -672,6 +1052,39 @@ msgstr "%(collection_title)s 편집 중" msgid "Editing %(username)s's profile" msgstr "%(username)sì˜ ê³„ì • ì •ë³´ ìˆ˜ì •ì¤‘..." +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -682,8 +1095,8 @@ msgstr "미디어는 다ìŒìœ¼ë¡œ 태그 ë˜ì—ˆìŠµë‹ˆë‹¤.: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "다운로드" @@ -706,7 +1119,8 @@ msgid "" msgstr "사운드 파ì¼ì„ ìž¬ìƒ í•˜ì‹œë ¤ë©´\n\tì´ê³³ì—서 ìµœì‹ ì˜ ë¸Œë¼ìš°ì ¸ë¥¼ 다운받으세요! <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "ì›ë³¸ 파ì¼" @@ -714,6 +1128,11 @@ msgstr "ì›ë³¸ 파ì¼" msgid "WebM file (Vorbis codec)" msgstr "WebM íŒŒì¼ (Vorbis ì½”ë±)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -724,70 +1143,267 @@ msgstr "WebM íŒŒì¼ (Vorbis ì½”ë±)" msgid "Image for %(media_title)s" msgstr "%(media_title)s ì´ë¯¸ì§€" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "WebM íŒŒì¼ (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "미디어 작업중..." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "ìž‘ì—…ì¤‘ì¸ ë¯¸ë””ì–´ê°€ 없습니다." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "ë‹¤ìŒ ìž‘ì—…ì„ í•˜ëŠ” ì¤‘ì— ì—…ë¡œë“œì— ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤.:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "지난 10ê°œì˜ ì—…ë¡œë“œ 목ë¡" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "모ìŒì§‘ 추가" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "미디어 등ë¡í•˜ê¸°" @@ -806,11 +1422,6 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>ì˜ %(collection_title)s" msgid "Edit" msgstr "ìˆ˜ì •" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "ì‚ì œ" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -822,7 +1433,7 @@ msgstr "%(title)s ì„ ì§€ìš°ì‹œê² ìŠµë‹ˆê¹Œ?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "%(collection_title)sì˜ %(media_title)sì„ ì‚ì œ í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "지우기" @@ -865,24 +1476,21 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>ì˜ ë¯¸ë””ì–´" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– <a href=\"%(user_url)s\">%(username)s</a>ì˜ ë¯¸ë””ì–´ë¥¼ ë³´ê³ ìžˆìŠµë‹ˆë‹¤." -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "ë§ê¸€ 달기" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "ë§ê¸€ 추가" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "ì—" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>부가 기능</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -907,85 +1515,107 @@ msgstr "갤러리ì—서 미디어 ìž‘ì—…ì„ í•˜ë©´ 해당 ë‚´ìš©ì„ ì¶”ì í• ìˆ msgid "Your last 10 successful uploads" msgstr "지난 10ê°œì˜ ì—…ë¡œë“œ 목ë¡" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)sì˜ ê³„ì • ì •ë³´" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "죄송합니다. 해당 ìœ ì €ë¥¼ 찾지 못했습니다." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "email ì¸ì¦ì´ 필요합니다." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "ì´ë¯¸ 완료했습니다! ì‚¬ìš©ìž ê³„ì •ì€ í™œì„±í™” ë˜ì–´ 있습니다." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "ê³§ email ì„ í†µí•´ 지침서가 ë„ì°©í• ê²ë‹ˆë‹¤." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "ì´ëŸ°ê²½ìš°ëŠ” ìž‘ë™í•˜ì§€ 않습니다.:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "ì¸ì¦ë©”ì¼ ë‹¤ì‹œ 보내기" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "누군가 해당 ì‚¬ìš©ìž ì´ë¦„으로 등ë¡ì€ 했으나, ì•„ì§ í™œì„±í™” 하지 않았습니다." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "ì •ìƒì ì¸ ê³„ì •ì´ë‚˜, ì¸ì¦ ë©”ì¼ì„ 잃어버리셨다면 <a href=\"%(login_url)s\">로그ì¸</a> ì„ í•˜ì‹œê³ ì¸ì¦ ë©”ì¼ì„ 새로 보내주세요." +msgid "%(username)s's profile" +msgstr "%(username)sì˜ ê³„ì • ì •ë³´" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "ë‹¹ì‹ ì— ëŒ€í•´ 소개해 보세요." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "ê³„ì • ì •ë³´ ìˆ˜ì •" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "ì´ ì‚¬ìš©ìžëŠ” ê³„ì • ì •ë³´ë¥¼ ìž…ë ¥í•˜ì§€ 않았습니다." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "%(username)sì˜ ëª¨ë“ ë¯¸ë””ì–´ 보기" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "ì´ê³³ì— 등ë¡í•œ 미디어가 나타나게 ë©ë‹ˆë‹¤. 하지만 ì•„ì§ ì•„ë¬´ëŸ° 미디어를 등ë¡í•˜ì§€ 않으셨네요." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "ì•„ì§ ì–´ë– í•œ ë¯¸ë””ì–´ë„ ì¡´ìž¬í•˜ì§€ 않습니다." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "email ì¸ì¦ì´ 필요합니다." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "ì´ë¯¸ 완료했습니다! ì‚¬ìš©ìž ê³„ì •ì€ í™œì„±í™” ë˜ì–´ 있습니다." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "ê³§ email ì„ í†µí•´ 지침서가 ë„ì°©í• ê²ë‹ˆë‹¤." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "ì´ëŸ°ê²½ìš°ëŠ” ìž‘ë™í•˜ì§€ 않습니다.:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "ì¸ì¦ë©”ì¼ ë‹¤ì‹œ 보내기" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "누군가 해당 ì‚¬ìš©ìž ì´ë¦„으로 등ë¡ì€ 했으나, ì•„ì§ í™œì„±í™” 하지 않았습니다." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "ì •ìƒì ì¸ ê³„ì •ì´ë‚˜, ì¸ì¦ ë©”ì¼ì„ 잃어버리셨다면 <a href=\"%(login_url)s\">로그ì¸</a> ì„ í•˜ì‹œê³ ì¸ì¦ ë©”ì¼ì„ 새로 보내주세요." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1034,50 +1664,85 @@ msgstr "최근" msgid "older" msgstr "ì´ì „" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "태그 ì •ë³´" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "ì´ë¯¸ì§€ 파ì¼ì„ ì½ì„ 수 없습니다." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "ì›ìФ!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "í¬ë©§íŒ…ì„ ìœ„í•´ <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> ì„ ì‚¬ìš©í• ìˆ˜ 있습니다.." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1099,73 +1764,84 @@ msgstr "-- ì„ íƒ --" msgid "Include a note" msgstr "노트 추가" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "ê²Œì‹œë¬¼ì— ë§ê¸€ì´ ë‹¬ë ¸ìŠµë‹ˆë‹¤." +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "오우, ëŒ“ê¸€ì´ ë¹„ì—ˆìŠµë‹ˆë‹¤." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "ëŒ“ê¸€ì´ ë“±ë¡ ë˜ì—ˆìŠµë‹ˆë‹¤!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "확ì¸ì„ í•˜ì‹œê³ ë‹¤ì‹œ 시ë„하세요." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "모ìŒì§‘ì„ ì¶”ê°€í•˜ê±°ë‚˜ 기존 모ìŒì§‘ì„ ì„ íƒí•˜ì„¸ìš”." -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" 모ìŒì§‘ì´ ì´ë¯¸ 존재 합니다. \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" 모ìŒì§‘ì„ ì¶”ê°€í–ˆìŠµë‹ˆë‹¤. \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "미디어를 ì‚ì œ 했습니다." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "í™•ì¸ ì²´í¬ë¥¼ 하지 않았습니다. 미디어는 ì‚ì œë˜ì§€ 않았습니다." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "다른 ì‚¬ëžŒì˜ ë¯¸ë””ì–´ë¥¼ ì‚ì œí•˜ë ¤ê³ í•©ë‹ˆë‹¤. 다시 한번 확ì¸í•˜ì„¸ìš”." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "모ìŒì§‘ì— ìžˆëŠ” í•ëª©ì„ ì‚ì œ 했습니다." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "확ì¸ì„ 하지 않았습니다. í•ëª©ì€ ì‚ì œí•˜ì§€ 않았습니다." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "다른 사용ìžì˜ 모ìŒì§‘ì— ìžˆëŠ” í•ëª©ì„ ì‚ì œí•˜ì˜€ìŠµë‹ˆë‹¤. 주ì˜í•˜ì„¸ìš”." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "\"%s\" 모ìŒì§‘ì„ ì‚ì œí•˜ì…¨ìŠµë‹ˆë‹¤." -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "확ì¸ì„ 하지 않았습니다. 모ìŒì§‘ì€ ì‚ì œí•˜ì§€ 않았습니다." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "다른 사용ìžì˜ 모ìŒì§‘ì„ ì‚ì œí•˜ë ¤ê³ í•©ë‹ˆë‹¤. 주ì˜í•˜ì„¸ìš”." diff --git a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo Binary files differindex fe96d40e..4b1246a8 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 3fd26d23..a157b4fd 100644 --- a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po @@ -3,16 +3,16 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <mail@jefvanschendel.nl>, 2011, 2012. -# <mvanderboom@gmail.com>, 2012. +# schendje <mail@jefvanschendel.nl>, 2011, 2012 +# mvanderboom <mvanderboom@gmail.com>, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Dutch (http://www.transifex.com/projects/p/mediagoblin/language/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -20,253 +20,264 @@ msgstr "" "Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Sorry, registratie is uitgeschakeld op deze instantie." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "" -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Gebruikersnaam" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Wachtwoord" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "E-mail adres" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Gebruikersnaam of email-adres" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Sorry, registratie is uitgeschakeld op deze instantie." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Sorry, er bestaat al een gebruiker met die naam." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Sorry, een gebruiker met dat e-mailadres bestaat al." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Uw e-mailadres is geverifieerd. U kunt nu inloggen, uw profiel bewerken, en afbeeldingen toevoegen!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "De verificatie sleutel of gebruikers-ID is onjuist" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Je moet ingelogd zijn, anders weten we niet waar we de e-mail naartoe moeten sturen!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Je hebt je e-mailadres al geverifieerd!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Verificatie e-mail opnieuw opgestuurd." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Een e-mail met instructies om je wachtwoord te veranderen is verstuurd." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Email kon niet verstuurd worden omdat je gebruikersnaam inactief is of omdat je e-mailadres nog niet geverifieerd is." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Je kunt nu inloggen met je nieuwe wachtwoord." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titel" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Beschrijving van dit werk" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Voor opmaak kun je <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> gebruiken." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Etiket" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Hou labels gescheiden met komma's." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Slug" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "De slug kan niet leeg zijn" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Het titelgedeelte van het adres van deze media. Normaal gesproken hoef je deze niet te veranderen." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Licentie" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Website" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Dit adres bevat fouten" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Oud wachtwoord" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Vul je oude wachtwoord in om te bewijzen dat dit jouw account is" +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nieuw wachtwoord" +msgid "Enable insite notifications about events." +msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Oud wachtwoord" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Vul je oude wachtwoord in om te bewijzen dat dit jouw account is" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nieuw wachtwoord" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Wachtwoord" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Er bestaat al een met die slug voor deze gebruiker." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "U bent de media van een andere gebruiker aan het aanpassen. Ga voorzichtig te werk." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "U bent een gebruikersprofiel aan het aanpassen. Ga voorzichtig te werk." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Profielaanpassingen opgeslagen" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Verkeerd wachtwoord" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Accountinstellingen opgeslagen" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Verkeerd wachtwoord" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -274,15 +285,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Sorry, dat bestandstype wordt niet ondersteunt." -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Gebruikersnaam" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "E-mail adres" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Gebruikersnaam of email-adres" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Een e-mail met instructies om je wachtwoord te veranderen is verstuurd." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Email kon niet verstuurd worden omdat je gebruikersnaam inactief is of omdat je e-mailadres nog niet geverifieerd is." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Je kunt nu inloggen met je nieuwe wachtwoord." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Voer je nieuwe wachtwoord in" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Wachtwoord opslaan" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Heeft u nog geen account?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Maak er hier een!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Wachtwoord herstellen" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Stuur instructies" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Wachtwoord vergeten?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Locatie" @@ -292,6 +490,10 @@ msgstr "Locatie" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Bekijken op <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -346,7 +548,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -359,223 +561,335 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Voeg toe" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Verwijderen" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Inloggen" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Inloggen is mislukt!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Verkeerd bestandsformaat voor mediatype opgegeven." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Bestand" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "U moet een bestand aangeven." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Mooizo! Toegevoegd!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Verifieer je e-mailadres!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Inloggen" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Accountinstellingen aanpassen" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Mediaverwerkingspaneel" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Voeg media toe" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." -msgstr "Uitgegeven onder de <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>-licentie. <a href=\"%(source_link)s\">Broncode</a> available." - -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Verkennen" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Hoi, welkom op deze MediaGoblin website!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." -msgstr "Deze website draait <a href=\"http://mediagoblin.org\">MediaGoblin</a>, een buitengewoon goed stuk software voor mediahosting." - -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" -msgstr "Heb je er nog geen? Het is heel eenvoudig!" - -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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\">Creëer een account op deze website</a>\n of\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Gebruik MediaGoblin op je eigen server</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Nieuwste media" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Media te verwerken" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Geen media om te verwerken" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Deze toevoegingen konden niet verwerkt worden:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Voer je nieuwe wachtwoord in" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Wachtwoord opslaan" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Wachtwoord herstellen" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Stuur instructies" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Hoi %(username)s,\n\nOm je wachtwoord voor GNU MediaGoblin te veranderen, moet je dit adres in je webbrowser openen:\n\n%(verification_url)s\n\nAls je denkt dat dit niet klopt, kun je deze e-mail gewoon negeren." +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Inloggen is mislukt!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Heeft u nog geen account?" +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Maak er hier een!" +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Wachtwoord vergeten?" +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "Maak een account aan!" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "Creëer" @@ -590,6 +904,62 @@ msgid "" "%(verification_url)s" msgstr "Hallo %(username)s , open de volgende URL in uw webbrowser om uw GNU MediaGoblin account te activeren: %(verification_url)s " +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "Uitgegeven onder de <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>-licentie. <a href=\"%(source_link)s\">Broncode</a> available." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Verkennen" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Hoi, welkom op deze MediaGoblin website!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "Deze website draait <a href=\"http://mediagoblin.org\">MediaGoblin</a>, een buitengewoon goed stuk software voor mediahosting." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "Heb je er nog geen? Het is heel eenvoudig!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +972,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -625,12 +995,18 @@ msgstr "Annuleren" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Wijzigingen opslaan" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -641,7 +1017,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Permanent verwijderen" @@ -658,10 +1034,14 @@ msgstr "%(media_title)s aanpassen" msgid "Changing %(username)s's account settings" msgstr "%(username)ss accountinstellingen aanpassen" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -673,6 +1053,39 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "Het profiel aanpassen van %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -683,8 +1096,8 @@ msgstr "Media met het label: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "" @@ -707,7 +1120,8 @@ msgid "" msgstr "U kunt een moderne web-browser die \n\taudio kan afspelen vinden op <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -715,6 +1129,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,70 +1144,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "Afbeelding voor %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Media te verwerken" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Geen media om te verwerken" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Deze toevoegingen konden niet verwerkt worden:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Voeg media toe" @@ -807,11 +1423,6 @@ msgstr "" msgid "Edit" msgstr "Pas aan" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Verwijderen" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,7 +1434,7 @@ msgstr "Zeker weten dat je %(title)s wil verwijderen?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -866,24 +1477,21 @@ msgstr "Media van <a href=\"%(user_url)s\"> %(username)s </a>" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Blader door media van <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Geef een reactie" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Voeg dit bericht toe" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "op" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Toegevoegd op</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -908,85 +1516,107 @@ msgstr "Hier kun je de status zien van de media die verwerkt worden." msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Profiel van %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Sorry, die gebruiker kon niet worden gevonden." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Emailverificatie is nodig" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Bijna klaar! Je account moet nog geactiveerd worden." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Een e-mail zou in een paar ogenblikken aan moeten komen met instructies hiertoe." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Zoniet:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Stuur de verificatie e-mail opnieuw op." +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Iemand heeft een account met deze gebruikersnaam gemaakt, maar hij moet nog geactiveerd worden." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Als u die persoon bent, maar de verificatie e-mail verloren hebt, kunt u <a href=\"%(login_url)s\">inloggen</a> en hem nogmaals verzenden." +msgid "%(username)s's profile" +msgstr "Profiel van %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Hier is een plekje om anderen over jezelf te vertellen." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Profiel aanpassen." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Deze gebruiker heeft zijn of haar profiel (nog) niet ingevuld." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Bekijk alle media van %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Dit is waar je nieuwe media zal verschijnen, maar het lijkt erop dat je nog niets heb toegevoegd." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Het lijkt erop dat er nog geen media is." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Emailverificatie is nodig" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Bijna klaar! Je account moet nog geactiveerd worden." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Een e-mail zou in een paar ogenblikken aan moeten komen met instructies hiertoe." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Zoniet:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Stuur de verificatie e-mail opnieuw op." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Iemand heeft een account met deze gebruikersnaam gemaakt, maar hij moet nog geactiveerd worden." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Als u die persoon bent, maar de verificatie e-mail verloren hebt, kunt u <a href=\"%(login_url)s\">inloggen</a> en hem nogmaals verzenden." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1035,50 +1665,85 @@ msgstr "nieuwer" msgid "older" msgstr "ouder" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Getagged met" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Kon het afbeeldingsbestand niet lezen." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Oeps!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Voor opmaak kun je <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> gebruiken." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1100,73 +1765,84 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Oeps, je bericht was leeg." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Je bericht is geplaatst!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Je hebt deze media verwijderd." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "Deze media was niet verwijderd omdat je niet hebt aangegeven dat je het zeker weet." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Je staat op het punt de media van iemand anders te verwijderen. Pas op." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo Binary files differindex f58e6a45..77ef3622 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 12d34b55..f974e3e1 100644 --- a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po @@ -3,15 +3,15 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <odin.omdal@gmail.com>, 2013. -# <odin.omdal@gmail.com>, 2011-2012. +# velmont <odin.omdal@gmail.com>, 2013 +# velmont <odin.omdal@gmail.com>, 2011-2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-10 13:31+0000\n" -"Last-Translator: velmont <odin.omdal@gmail.com>\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: Norwegian Nynorsk (Norway) (http://www.transifex.com/projects/p/mediagoblin/language/nn_NO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -20,253 +20,264 @@ msgstr "" "Language: nn_NO\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Registrering er slege av. Orsak." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "Rapportering er slege av. Orsak." + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "Autentisering er slege av. Orsak." + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "Ugyldig brukarnamn eller passord." -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "Dette feltet tek ikkje epostadresser." -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "Dette feltet krev ei epostadresse." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Brukarnamn" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Passord" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Epost" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Brukarnamn eller epost" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Registrering er slege av. Orsak." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Ein konto med dette brukarnamnet finst allereide." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Ein brukar med den epostadressa finst allereie." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "Stadfestingsnykelen eller brukar-ID-en din er feil." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Kontoen din er stadfesta. Du kan no logga inn, endra profilen din og lasta opp filer." -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Stadfestingsnykelen eller brukar-ID-en din er feil." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Du mÃ¥ vera innlogga, slik me veit kven som skal ha eposten." -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Du har allereie verifisiert epostadressa." -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." -msgstr "Send ein ny stadfestingsepost." - -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "Dersom denne epostadressa er registrert, har ein epost med instruksjonar for Ã¥ endra passord vorte sendt til han." - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "Fann ingen med det brukarnamnet." +msgstr "Stadfestingsepost sendt." -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Sender epost med instruksjonar for Ã¥ endra passordet ditt." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Kunne ikkje senda epost. Brukarnamnet ditt er inaktivt eller uverifisert." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Du kan no logga inn med det nye passordet ditt." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Tittel" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Skildring av verk" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Du kan bruka <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> til formattering." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Merkelappar" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Separer merkelappar med komma." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Nettnamn" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "Nettnamnet kan ikkje vera tomt" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Nettnamnet (adressetittel) for verket di. Trengst ikkje endrast." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Lisens" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Presentasjon" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Heimeside" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Adressa inneheld feil" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Gamalt passort" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Skriv inn det gamle passordet ditt for Ã¥ stadfesta at du eig denne kontoen." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Send meg epost nÃ¥r andre kjem med innspel pÃ¥ verka mine." #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nytt passord" +msgid "Enable insite notifications about events." +msgstr "SlÃ¥ av/pÃ¥ notifikasjonar om hendingar." -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "Lisens-val" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "Dette vil vera standardvalet ditt for lisens." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Send meg epost nÃ¥r andre kjem med innspel pÃ¥ verka mine." - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "Tittelen kjan ikkje vera tom" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Forklaringa til denne samlinga" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "Tittel-delen av denne samlinga si adresse. Du treng normalt sett ikkje endra denne." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Gamalt passort" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Skriv inn det gamle passordet ditt for Ã¥ stadfesta at du eig denne kontoen." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nytt passord" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Ny epostadresse" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Passord" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Skriv inn passordet som prov pÃ¥ at dette er din konto." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Eit innlegg med denne adressetittelen finst allereie." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "TrÃ¥ varsamt, du endrar nokon andre sine verk." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "La til vedlegg %s." -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "Du kan berre enda din eigen profil." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "TrÃ¥ varsamt, du endrar nokon andre sin profil." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Lagra endring av profilen" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Feil passord" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Lagra kontoinstellingar" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "Du mÃ¥ stadfesta slettinga av kontoen din." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Du har allereie ei samling med namn «%s»." -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "Ei samling med den nettadressa finst allereie for denne brukaren." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Du endrar ein annan brukar si samling. TrÃ¥ varsamt." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Epostadressa di er bekrefta." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Feil passord" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Cannot link theme... no theme set\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "No asset directory for this theme\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "However, old link directory symlink found; removed.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "Kunne ikkje lenkja «%s»: %s eksisterer og er ikkje ei symlenkje\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "Hopper over «%s»: allereie satt opp.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "Gamal lenkje funnen for «%s»; fjernar.\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -274,15 +285,202 @@ msgid "" "domain." msgstr "Finn ikkje CSRF-cookien. Dette er truleg grunna ein cookie-blokkar.<br/>\nSjÃ¥ til at du tillet cookies for dette domenet." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Orsak, stør ikkje den filtypen :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "klarte ikkje køyra unoconv, sjekk logg-fil" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Skjedde noko gale med video transkodinga" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "Ta-med-privilegium" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "Bannlys brukaren" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "Send brukaren ei melding" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "Slett innhaldet" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "Brukaren vil bli bannlyst til:" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "Kvifor bannlyser du denne brukaren?" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "Kva handling vil du ta for Ã¥ løysa rapporteringa?" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "Kva privilegium vil du ta vekk?" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "Ã…tvaring frÃ¥" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "kom med innspel pÃ¥ innlegget ditt" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "Tingar innspel frÃ¥ %s." + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "Du vil ikkje fÃ¥ notifikasjonar for innspel pÃ¥ %s." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "Treng oauth_token (must provide oath_token)." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "Noko gjekk gale :( (no request token found)." + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "Fila er for stor." + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "Opplasting av denne fila vil putta deg over opplastingsgrensa di." + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "Du har nÃ¥dd opplastingsgrensa di." + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Brukarnamn" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Epost" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Brukarnamn eller epost" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "Hald meg innlogga" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Brukarnamn eller epost" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Dersom denne epostadressa er registrert, har ein epost med instruksjonar for Ã¥ endra passord vorte sendt til han." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Fann ingen med det brukarnamnet." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Sender epost med instruksjonar for Ã¥ endra passordet ditt." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Kunne ikkje senda epost. Brukarnamnet ditt er inaktivt eller ikkje stadfesta." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "Brukar-ID-en er feil." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Du kan no logga inn med det nye passordet ditt." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "Brukaren er ikkje aktiv. Kontakt administrator for Ã¥ aktivera kontoen din att." + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Endra passord" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Lag nytt passord" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Set passord" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Endrar passordet til %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Lagra" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Manglar du konto?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Opprett ein!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "Endra passordet ditt." + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Gløymd passordet?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Send instruksjonar" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Gløymd passordet?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Stad" @@ -292,6 +490,10 @@ msgstr "Stad" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "SjÃ¥ pÃ¥ <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "Logg inn for Ã¥ oppretta ein konto." + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Godta" @@ -346,7 +548,7 @@ msgstr "Omdirigerings-URI-en for programmene. Denne feltet <strong>krevst</stron msgid "This field is required for public clients" msgstr "Dette feltet krevst for opne (public) klientar" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Klienten {0} er registrert." @@ -359,88 +561,357 @@ msgid "Your OAuth clients" msgstr "Dine OAuth-klientar" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Legg til" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "Ein konto er allereie registrert til den OpenID-en." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "Fann ikkje OpenID-tenaren." + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "Ingen OpenID funne for %s." + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Stadfesting av %s feila: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Stadfesting avbrutt" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "Lagra OpenID-url." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "Kan ikkje sletta den einaste OpenID-urlen utan at du har eit passord satt." + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "Den OpenID-en er ikkje registrert til denne kontoen." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "Fjerna OpenID-en." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Legg til OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Slett ein OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Slett" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "OpenID-ar" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Logg inn" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Innlogging feila" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "Logg inn for Ã¥ oppretta ein konto" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "Eller logg inn med passord." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "Eller logg inn med OpenID." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "Eller registrer med OpenID." + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "Ein konto er allereie registrert til den Persona-eposten." + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "Persone-eposten fjerna." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "Du kan ikkje sletta din einaste Persona-epostadresse utan eit passord satt." + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "Den Persona-epostadressa er ikkje registrert til denne kontoen." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "Ein konto med den Persona-epostadressa finst allereie." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Persone-epostadressa lagra." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "Fjern ei Persona-epostadresse" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "Ny Persona-epostadresse" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "Personaer" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "Eller logg inn med Persona." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "Eller registrer med Persona." + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Ugyldig fil for medietypen." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "Klarte ikkje kopiera til «public storage»." + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "Fann ingen akseptable filar for prosessering." + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "Maks filstorleik: {0} mb" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Fil" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "Du kan bruka\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> til formattering." + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Du mÃ¥ velja ei fil." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Johoo! Opplasta!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "La til samlinga «%s»." -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "Du er bannlyst." + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Bilete av stressa goblin" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "Du har blitt bannlyst." + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "til %(until_when)s" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "for alltid" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" -msgstr "Verifiser epostadressa di." +msgstr "Stadfest epostadressa di." -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "Logg ut" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Logg inn" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "<a href=\"%(user_url)s\">%(user_name)s</a> sin konto" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Endra kontoinstellingar" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Verkprosesseringspanel" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "Logg ut" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Legg til verk" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Lag ny samling" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "Brukaradministrasjon" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "Rapporteringsadministrasjon" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Nyaste verk" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Godkjenning" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "Godkjenn" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Du er innlogga som" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "Vil du godkjenna" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "som ukjend applikasjon" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "Ã¥ fÃ¥ tilgang til kontoen din?" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Applikasjonar med tilgang til kontoen din kan:" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "Leggja til media som deg" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "SjÃ¥ informasjonen din (t.d. profil, bilete, osb...)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "Endra informasjonen din" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "Godkjenning ferdig" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "Godkjenning ferdig" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Kopier og lim inn dette i klienten din:" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Opprett ein konto." + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Opprett" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Hei %(username)s,\n\nopna fylgjande netadresse i netlesaren din for Ã¥ aktivera kontoen din:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." msgstr "Drive av <a href=\"http://mediagoblin.org\" title='Version %(version)s'>MediaGoblin</a>, eit <a href=\"http://gnu.org/\">GNU</a>-prosjekt." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -448,147 +919,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Lisensiert med <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Kjeldekode</a> er tilgjengeleg." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "Bilete av stressa goblin" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "BruksvilkÃ¥r" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "Utforsk" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Heihei, velkomen til denne MediaGoblin-sida." -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 msgid "" "This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " "extraordinarily great piece of media hosting software." msgstr "Denne sida køyrer <a href=\"http://mediagoblin.org\">MediaGoblin</a>, eit superbra program for Ã¥ visa fram dine kreative verk." -#: mediagoblin/templates/mediagoblin/root.html:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Vil du leggja til eigne verk og innpel, so mÃ¥ du logga inn." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "Har du ikkje ein enno? Det er enkelt!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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\">Opprett ein konto pÃ¥ denne sida</a> eller <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">set opp MediaGoblin pÃ¥ eigen tenar</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Nyaste verk" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Hald oppsyn med statusen for prosessering av verka dine her." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Verk under prosessesering" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Ingen verk vert prosessert" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Klarte ikkje prosessera desse opplasta filene:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Ingen feila filer." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "Dei siste ti opplastningane" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Ingenting prossesert, enno." - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Lag nytt passord" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Set passord" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Gløymd passordet?" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Send instruksjonar" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" "\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Hei %(username)s,\n\nfor Ã¥ endra MediaGoblin-passordet ditt, opna fylgjande URL i ein netlesar:\n\n <%(verification_url)s>\n\nDersom du mistenkjer dette er eit misstak, ignorer eposten og hald fram med Ã¥ vera ein glad goblin!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Innlogging feila" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Har du ingen konto?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Lag ein!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Gløymd passordet?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Lag ein konto." - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Opprett" +" >Create an account at this site</a>\n" +" or" +msgstr "\n>Opprett ein konto pÃ¥ denne sida</a>\neller" -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" -"\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" "\n" -"%(verification_url)s" -msgstr "Hei %(username)s,\n\nopna fylgjande netadresse i netlesaren din for Ã¥ aktivera kontoen din:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set opp din eigen MediaGoblin-server</a>" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -602,13 +972,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Endrar vedlegg for %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Vedlegg" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Legg ved vedlegg" @@ -625,12 +995,18 @@ msgstr "Bryt av" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Lagra" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Endrar eposten til %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -641,7 +1017,7 @@ msgid "Yes, really delete my account" msgstr "Ja, slett kontoen min" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Slett permanent" @@ -658,10 +1034,14 @@ msgstr "Endrar %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "Endrar kontoinnstellingane til %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "Slett kontoen min" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Epost" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -673,6 +1053,39 @@ msgstr "Endrar %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Endrar profilen til %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "Hei!\n\nMe ynskjer Ã¥ stadfesta at du er %(username)s. Dersom du er\nfylg denne lenkja for Ã¥ stadfesta epostadressa di:\n\n%(verification_url)s\n\nDersom du ikkje er %(username)s eller ikkje ynskjer ei epost-endring kan du\nberre ignorera denne eposten." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Nye innspel" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)s sidan" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Marker alt lese" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -683,8 +1096,8 @@ msgstr "Verk merka med: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Last ned" @@ -707,7 +1120,8 @@ msgid "" msgstr "Du kan skaffa ein moderne netlesar som kan spela av dette lydklippet hjÃ¥ <a href=\"http://opera.com/download\">http://opera.com/download</a>." #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Opphavleg fil" @@ -715,6 +1129,11 @@ msgstr "Opphavleg fil" msgid "WebM file (Vorbis codec)" msgstr "WebM-fil (Vorbis-kodek)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Oppretta" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,70 +1144,267 @@ msgstr "WebM-fil (Vorbis-kodek)" msgid "Image for %(media_title)s" msgstr "Bilete for %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "SlÃ¥ av/pÃ¥ rotering" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF-fil" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "Perspektiv" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "Front" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "Topp" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "Side" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "Last ned modell" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "Filformat" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "Objekthøgd" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "Orsak, denne videoen fungerer ikkje\nfordi netlesaren din ikkje stør\nHTML5 video." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "Du kan skaffa deg ein moderne netlesar som kan spela denne videoen hjÃ¥ <a href=http://opera.com>http://opera.com</a> eller <a href=\"http://getfirefox.com\">http://getfirefox.com</a>." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "WebM fil (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "WebM-fil (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Hald oppsyn med statusen for prosessering av verka dine her." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Verk under prosessesering" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Ingen verk vert prosessert" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Klarte ikkje prosessera desse opplasta filene:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Ingen feila filer." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Dei siste ti opplastningane" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Ingenting prossesert, enno." + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "Fann ikkje rapporten." + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "Attende til rapporteringspanelet" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "Rapport" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "Rapportert innspel" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "\n â– Rapportert verk av <a href=\"%(user_url)s\">%(user_name)s</a>\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "\n INNHALD AV\n <a href=\"%(user_url)s\"> %(user_name)s</a>\n ER SLETTA\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "Løys" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "Løys denne rapporten" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "Status" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "LØYST" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "Du kan ikkje handla mot ein administrator" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "Rapporteringspanel" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "\nHer kan du sjÃ¥ opne rapportar som brukarane dine har lagt til." + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "Aktive rapportar" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "Skulda" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "Rapportert" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "Rapportert av" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "Ã…rsak" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "\n Innspelsrapport #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "\n Verk-rapport #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "Ingen opne rapportar." + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "Løyste rapportar" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "Løyst" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "Handling teke" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "\nLukka rapport #%(report_id)s" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "Ingen lukka rapportar." + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "Brukarpanel" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "\nHer kan du slÃ¥ opp brukarar og straffa dei." + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "Aktive brukarar" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "ID" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "Vart med" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "Tal pÃ¥ innspel" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "Fann ingen brukarar." #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Legg til ei samling" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Legg til verk" @@ -807,11 +1423,6 @@ msgstr "%(collection_title)s av <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "Endra" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Slett" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,7 +1434,7 @@ msgstr "Vil du verkeleg sletta %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Fjerna %(media_title)s frÃ¥ %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Fjern" @@ -866,24 +1477,21 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a> sine verk" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Ser pÃ¥ <a href=\"%(user_url)s\">%(username)s</a> sine verk" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Legg att innspel" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Legg til dette innspelet" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "hjÃ¥" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Førehandsvisning av innspel" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Lagt til</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Lagt til" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -908,85 +1516,107 @@ msgstr "SjÃ¥ status for prosessering av verka dine her." msgid "Your last 10 successful uploads" msgstr "Dine ti siste opplastningar." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)s sin profil" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "<h2>Rapportér</h2>" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Fann ingen slik brukar" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "Rapporterer dette innspelet" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Epostverifisering trengst." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "Rapporterer dette verket" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Nesten ferdig. Du treng berre aktivera kontoen." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 -msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Ein epost med instruksjonar kjem straks." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "I tilfelle det ikkje skjer:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Send ein ny epost" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Dette brukarnamnet finst allereie, men det er ikkje aktivert." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 #, python-format msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Viss dette er deg, kan du <a href=\"%(login_url)s\">logga inn</a> for Ã¥ fÃ¥ tilsendt ny epost med stadfestingslenkje." +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "\n â– Publisert av <a href=\"%(user_url)s\"\n class=\"comment_authorlink\">%(username)s</a>\n " + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "Rapportér" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 +#, python-format +msgid "%(username)s's profile" +msgstr "%(username)s sin profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Her kan du fortelja om deg sjølv." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Endra profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Brukaren har ikkje fylt ut profilen sin (enno)." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "SjÃ¥ gjennom samlingar" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "SjÃ¥ alle %(username)s sine verk" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Her kjem verka dine." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Ser ikkje ut til at det finst nokon verk her nett no." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Treng stadfesting av epostadressa" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Nesten ferdig. Du treng berre aktivera kontoen." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Ein epost med instruksjonar kjem straks." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "I tilfelle det ikkje skjer:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Send ein ny stadfestingsepost" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Dette brukarnamnet finst allereie, men det er ikkje aktivert." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Viss dette er deg, kan du <a href=\"%(login_url)s\">logga inn</a> for Ã¥ fÃ¥ tilsendt ny epost med stadfestingslenkje." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "(fjern)" @@ -1035,50 +1665,85 @@ msgstr "nyare" msgid "older" msgstr "eldre" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "Rapportér verk" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Merka med" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Klarte ikkje lesa biletefila." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Oops." -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Noko gjekk gale" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Bad Request (noko gjekk gale)" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "The request sent to the server is invalid, please double check it" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "Ulovleg operasjon" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "Orsak Dave, eg kan ikkje la deg gjera det!<HAL2000></p>\n<p>Du prøvde Ã¥ gjera noko du ikkje har løyve til. Prøvar du Ã¥ sletta alle brukarkonti no igjen?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "Ser ikkje ut til Ã¥ finnast noko her. Orsak.</p>\n<p>Dersom du er sikker pÃ¥ at adressa finst, so er ho truleg flytta eller sletta." +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "Ã¥r" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "mÃ¥nad" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "veke" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "dag" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "time" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minutt" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "Innspel" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Du kan bruka <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> til formatterring." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Du kan bruka <a href=\"http://daringfireball.net/projects/markdown/basics\" target=_blank>Markdown</a> til formatterring." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1100,73 +1765,84 @@ msgstr "-- Vel --" msgid "Include a note" msgstr "Legg ved eit notat" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "kom med innspel pÃ¥ innlegget ditt" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Du kan bruka <a href=\"http://daringfireball.net/projects/markdown/basics\" target=_blank>Markdown</a> til formattering." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "Ã…rsak for rapportering" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Innspel er avslege" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Vops, innspelet ditt var tomt." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Innspelet ditt er lagt til." -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "Sjekk filene dine og prøv omatt." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Du mÃ¥ velja eller laga ei samling" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "«%s» er allereie i samling «%s»" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "«%s» lagt til samling «%s»" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Du sletta verket." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "Sletta ikkje verket." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Du er i ferd med Ã¥ sletta ein annan brukar sine verk. TrÃ¥ varsamt." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Du fjerna fila frÃ¥ samlinga." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "Fila var ikkje fjerna fordi du ikkje var sikker." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Du er i ferd med Ã¥ fjerna ei fil frÃ¥ ein annan brukar si samling. TrÃ¥ varsamt." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Samlinga «%s» sletta" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "Sletta ikkje samlinga." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Du er i ferd med Ã¥ sletta ein annan brukar si samling. TrÃ¥ varsamt." diff --git a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mo Binary files differindex ea905b61..98e1ceed 100644 --- a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po index 9edf8e2b..f2af3cd1 100644 --- a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po @@ -3,15 +3,16 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Daniel Koć <kocio@aster.pl>, 2012. +# Daniel Koć <daniel@xn--ko-wla.pl>, 2012 +# Sergiusz Pawlowicz <transifex@pawlowicz.name>, 2013 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Polish (http://www.transifex.com/projects/p/mediagoblin/language/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,269 +20,467 @@ msgstr "" "Language: pl\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Niestety rejestracja w tym serwisie jest wyłączona." -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Użytkownik" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "HasÅ‚o" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "Przepraszamy, autoryzacja jest wyłączona w tym systemie." -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Adres e-mail" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "NieprawidÅ‚owa nazwa konta albo niewÅ‚aÅ›ciwy adres poczty elektronicznej." -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Użytkownik lub adres e-mail" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "Niniejsze pole nie jest przeznaczone na adres poczty elektronicznej." -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Niestety rejestracja w tym serwisie jest wyłączona." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "Niniejsze pole wymaga podania adresu poczty elektronicznej." -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Niestety użytkownik o takiej nazwie już istnieje." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Niestety użytkownik z tym adresem e-mail już istnieje." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "Klucz kontrolny albo identyfikator użytkownika jest nieprawidÅ‚owy." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Twój adres e-mail zostaÅ‚ zweryfikowany. Możesz siÄ™ teraz zalogować, wypeÅ‚nić opis swojego profilu i wysyÅ‚ać grafiki!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "NieprawidÅ‚owy klucz weryfikacji lub identyfikator użytkownika." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Musisz siÄ™ zalogować żebyÅ›my wiedzieli do kogo wysÅ‚ać e-mail!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Twój adres e-mail już zostaÅ‚ zweryfikowany!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "WyÅ›lij ponownie e-mail weryfikujÄ…cy." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "WysÅ‚ano e-mail z instrukcjami jak zmienić hasÅ‚o." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Nie udaÅ‚o siÄ™ wysÅ‚ać e-maila w celu odzyskania hasÅ‚a, ponieważ twoje konto jest nieaktywne lub twój adres e-mail nie zostaÅ‚ zweryfikowany." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Teraz możesz siÄ™ zalogować używajÄ…c nowe hasÅ‚o." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "TytuÅ‚" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Opis tej pracy" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Możesz formatować tekst za pomocÄ… skÅ‚adni \n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a>." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Znaczniki" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Rozdzielaj znaczniki przecinkami." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Slug" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "Slug nie może być pusty" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Fragment adresu mediów zawierajÄ…cy tytuÅ‚. Zwykle nie ma potrzeby aby go zmieniać." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Licencja" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Biogram" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Strona internetowa" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Ten adres zawiera błędy" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Stare hasÅ‚o" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Wprowadź swoje stare hasÅ‚o aby udowodnić, że to twoje konto." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Powiadamiaj mnie e-mailem o komentarzach do moich mediów" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nowe hasÅ‚o" +msgid "Enable insite notifications about events." +msgstr "Włącz powiadomienia dotyczÄ…ce wydarzeÅ„" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" -msgstr "" +msgstr "Ulubiona licencja" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" +msgstr "To bÄ™dzie twoja domyÅ›lna licencja dla wgrywanych mediów." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Powiadamiaj mnie e-mailem o komentarzach do moich mediów" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "TytuÅ‚ nie może być pusty" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Opis tej kolekcji" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "Część adresu zawierajÄ…ca tytuÅ‚. Zwykle nie musisz tego zmieniać." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Stare hasÅ‚o" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Wprowadź swoje stare hasÅ‚o aby udowodnić, że to twoje konto." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nowe hasÅ‚o" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Nowy adres poczty elektronicznej" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "HasÅ‚o" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Wprowadź swoje hasÅ‚o aby potwierdzić, że jesteÅ› wÅ‚aÅ›cicielem konta." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Adres z tym slugiem dla tego użytkownika już istnieje." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Edytujesz media innego użytkownika. Zachowaj ostrożność." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" -msgstr "" +msgstr "DodaÅ‚eÅ› załącznik %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." -msgstr "" +msgstr "Masz możliwość edycji tylko wÅ‚asnego profilu." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Edytujesz profil innego użytkownika. Zachowaj ostrożność." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Zapisano zmiany profilu" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "NieprawidÅ‚owe hasÅ‚o" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Zapisano ustawienia konta" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." -msgstr "" +msgstr "Musisz potwierdzić, że chcesz skasować swoje konto." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Kolekcja \"%s\" już istnieje!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "Kolekcja tego użytkownika z takim slugiem już istnieje." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Edytujesz kolekcjÄ™ innego użytkownika. Zachowaj ostrożność." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Twój adres poczty elektronicznej zostaÅ‚ potwierdzony." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "NieprawidÅ‚owe hasÅ‚o" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Nie można podlinkować motywu... nie wybrano motywu\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "Brak katalogu danych dla tego motywu\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "Znaleziono stary odnoÅ›nik symboliczny do katalogu; usuniÄ™to.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "Nie mogÄ™ zrobić odnoÅ›nika \"%s\": %s istnieje i nie jest odnoÅ›nikiem\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "Opuszczam \"%s\"; już jest gotowe.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "Znaleziono stary odnoÅ›nik dla \"%s\"; usuwam.\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.<br/>Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "Ciasteczko CSFR nie jest dostÄ™pne. Najprawdopodobniej stosujesz jakÄ…Å› formÄ™ blokowania ciasteczek.<br/>Upewnij siÄ™, że nasz serwer może zakÅ‚adać ciasteczka w twojej przeglÄ…darce." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "NIestety, nie obsÅ‚ugujemy tego typu plików :-(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "nie daÅ‚o siÄ™ uruchomić unoconv, sprawdź log" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Konwersja wideo nie powiodÅ‚a siÄ™" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "komentarze do twojego wpisu" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "Zaprenumerowano komentarze do %s!" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "Nie bÄ™dziesz otrzymywać komentarzy do %s." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "Musisz podać oauth_token." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "Nie znaleziono żetonu żądania." + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Użytkownik" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Adres e-mail" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Nazwa konta lub adres poczty elektronicznej" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "PozostaÅ„ zalogowany" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Użytkownik lub adres e-mail" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "JeÅ›li ten adres poczty elektronicznej istnieje (uwzglÄ™dniajÄ…c wielkość liter!), wysÅ‚ano na niego list z instrukcjÄ…, w jaki sposób możesz zmienić swoje hasÅ‚o." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Nie potrafiÄ™ znaleźć nikogo o tej nazwie użytkownika." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "WysÅ‚ano e-mail z instrukcjami jak zmienić hasÅ‚o." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Nie udaÅ‚o siÄ™ wysÅ‚ać e-maila w celu odzyskania hasÅ‚a, ponieważ twoje konto jest nieaktywne lub twój adres e-mail nie zostaÅ‚ zweryfikowany." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "Identyfikator użytkownika nie jest prawidÅ‚owy." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Teraz możesz siÄ™ zalogować używajÄ…c nowego hasÅ‚a." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Twoje hasÅ‚o zostaÅ‚o zmienione" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Podaj swoje nowe hasÅ‚o" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Podaj hasÅ‚o" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Zmieniam hasÅ‚o użytkownika %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Zachowaj" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Nie masz jeszcze konta?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Utwórz je tutaj!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Odtwórz hasÅ‚o" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "WyÅ›lij instrukcje" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "ZapomniaÅ‚eÅ› hasÅ‚a?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "PoÅ‚ożenie" @@ -291,6 +490,10 @@ msgstr "PoÅ‚ożenie" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Zobacz na <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Zezwól" @@ -315,7 +518,7 @@ msgstr "Opis" msgid "" "This will be visible to users allowing your\n" " application to authenticate as them." -msgstr "" +msgstr "To bÄ™dzie widoczne dla użytkowników, pozwalajÄ…c⎠twojej aplikacji uwierzytelniać siÄ™ jako oni." #: mediagoblin/plugins/oauth/forms.py:40 msgid "Type" @@ -345,101 +548,370 @@ msgstr "Przekierowanie URI dla aplikacji, to pole\n jest <strong>wyma msgid "This field is required for public clients" msgstr "To pole jest wymagane dla klientów publicznych" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Klient {0} zostaÅ‚ zarejestrowany!" #: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 msgid "OAuth client connections" -msgstr "" +msgstr "Połączenia do OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "Twoi klienci OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Dodaj" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "Przepraszamy, ale istnieje już konto zarejestrowane z tym OpenID." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "Przepraszamy, serwer OpenID nie zostaÅ‚ znaleziony" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "Nie znaleziono serwisu OpenID dla %s" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Potwierdzenie %s nie powiodÅ‚o siÄ™: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Potwierdzenie anulowane" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "Twój OpenID url zostaÅ‚ pomyÅ›lnie zachowany." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "Wskazane OpenID nie jest powiÄ…zane z niniejszym kontem." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "Konto OpenID zostaÅ‚o pomyÅ›lnie usuniÄ™te." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Dodaj konto OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "UsuÅ„ konto OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "UsuÅ„" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Zaloguj siÄ™" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Logowanie nie powiodÅ‚o siÄ™!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "Zaloguj siÄ™, aby utworzyć konto!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "Albo zaloguj siÄ™ hasÅ‚em!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "Albo zaloguj siÄ™ kontem OpenID!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "Lub zarejestruj siÄ™ z OpenID!" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "Konto zwiÄ…zane z Persona zostaÅ‚o pomyÅ›lnie usuniÄ™te." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "Nie możesz usunąć adresu poczty elektronicznej powiÄ…zanego z systemem Persona, gdyż twoje konto zostanie wtedy bez jakiegokolwiek hasÅ‚a." + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "Niniejsze konto nie jest powiÄ…zane z adresem poczty elektronicznej w Persona." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Twój adres poczty elektronicznej powiÄ…zany z Persona zostaÅ‚ zachowany pomyÅ›lnie." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "UsuÅ„ adres poczty elektronicznej powiÄ…zany z kontem Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "Dodaj adres poczty elektronicznej powiÄ…zany z kontem Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "Lub zaloguj z kontem Persona!" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "Lub zarejestruj z kontem Persona!" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "NiewÅ‚aÅ›ciwy plik dla tego rodzaju mediów." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "Kopiowanie do dysku publicznego nie powiodÅ‚o siÄ™." + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Plik" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Musisz podać plik." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Hura! WysÅ‚ano!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "Kolekcja \"%s\" zostaÅ‚a dodana!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Grafika zestresowanego goblina" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Zweryfikuj swój adres e-mail!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Zaloguj siÄ™" +msgstr "wyloguj siÄ™" -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" -msgstr "" +msgstr "konto <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "ZmieÅ„ ustawienia konta" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Panel przetwarzania mediów" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "Wyloguj siÄ™" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Dodaj media" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" +msgstr "Utwórz nowÄ… kolekcjÄ™" + +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Najnowsze media" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Uwierzytelnianie" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "Uwierzytelnij" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "JesteÅ› zalogowany jako" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "Czy chcesz uwierzytelnić" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "nieznana aplikacja" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "na dostÄ™p do twojego konta?" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Aplikacje z dostÄ™pem do twojego konta majÄ… prawo do:" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "Opublikuj nowe media na swoim koncie" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "Zobacz swoje dane (np. profil, media, itp.)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "ZmieÅ„ swoje dane" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "Uwierzytelnianie zakoÅ„czone." + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "Uwierzytelnianie zakoÅ„czone." + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Skopiuj i wklej to do swojego klienta:" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Utwórz konto!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Utwórz" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Cześć %(username)s,\n\naby aktywować twoje konto GNU MediaGoblin, otwórz nastÄ™pujÄ…cÄ… stronÄ™ w swojej przeglÄ…darce:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." -msgstr "" +msgstr "NapÄ™dzane przez oprogramowanie <a href=\"http://mediagoblin.org/\" title='w wersji %(version)s'>MediaGoblin</a>, bÄ™dÄ…ce częściÄ… projektu <a href=\"http://gnu.org/\">GNU</a>." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -447,147 +919,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Opublikowane na licencji <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. DostÄ™pny jest <a href=\"%(source_link)s\">kod źródÅ‚owy</a>." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "Odkrywaj" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Cześć, witaj na stronie MediaGoblin!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 msgid "" "This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " "extraordinarily great piece of media hosting software." msgstr "Ten serwis dziaÅ‚a w oparciu o <a href=\"http://mediagoblin.org\">MediaGoblin</a>, Å›wietne oprogramowanie do publikowania mediów." -#: mediagoblin/templates/mediagoblin/root.html:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Aby dodawać swoje pliki, komentować i wykonywać inne czynnoÅ›ci, możesz siÄ™ zalogować na swoje konto MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "Jeszcze go nie masz? To proste!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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\">Utwórz konto w tym serwisie</a>\n lub\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">załóż wÅ‚asny serwis MediaGoblin</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Najnowsze media" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Tu możesz Å›ledzić stan przetwarzania mediów na tym serwerze." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Przetwarzane media" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Å»adne media nie sÄ… obecnie przetwarzane" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "NIe udaÅ‚o siÄ™ przesÅ‚ać tych plików:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Brak nieprzetworzonych wpisów!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "Ostatnie 10 udanych wysyÅ‚ek" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Na razie nie przetworzono żadnego wpisu!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Podaj swoje nowe hasÅ‚o" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Podaj hasÅ‚o" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Odtwórz hasÅ‚o" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "WyÅ›lij instrukcje" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" "\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Cześć %(username)s,\n\naby zmienić twoje hasÅ‚o dla GNU MediaGoblin, otwórz nastÄ™pujÄ…cÄ… stronÄ™ w swojej przeglÄ…darce:\n\n%(verification_url)s\n\nJeÅ›li sÄ…dzisz, że to pomyÅ‚ka, po prostu zignoruj tÄ™ wiadomość i bÄ…dź nadal szczęśliwym goblinem!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Logowanie nie powiodÅ‚o siÄ™!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Nie masz jeszcze konta?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Utwórz je tutaj!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "ZapomniaÅ‚eÅ› hasÅ‚a?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Utwórz konto!" +" >Create an account at this site</a>\n" +" or" +msgstr "\n>Stwórz konto w serwisie</a>\nalbo" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Utwórz" - -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" "\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" -"\n" -"%(verification_url)s" -msgstr "Cześć %(username)s,\n\naby aktywować twoje konto GNU MediaGoblin, otwórz nastÄ™pujÄ…cÄ… stronÄ™ w swojej przeglÄ…darce:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -601,13 +972,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Edycja załączników do %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Załączniki" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Dodaj załącznik" @@ -624,23 +995,29 @@ msgstr "Anuluj" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Zapisz zmiany" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Zmieniam konto poczty elektronicznej dla %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" -msgstr "" +msgstr "Czy naprawdÄ™ skasować użytkownika '%(user_name)s' oraz usunąć wszystkie jego pliki i komentarze?" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 msgid "Yes, really delete my account" -msgstr "" +msgstr "Tak, naprawdÄ™ chcÄ™ skasować swoje konto" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "UsuÅ„ na staÅ‚e" @@ -657,9 +1034,13 @@ msgstr "Edytowanie %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "Zmiana ustawieÅ„ konta %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" -msgstr "" +msgstr "UsuÅ„ moje konto" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Adres poczty elektronicznej" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format @@ -672,6 +1053,39 @@ msgstr "Edycja %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Edycja profilu %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Nowe komentarze" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)s temu" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Oznacz wszystkie jako przeczytane" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -682,8 +1096,8 @@ msgstr "Media ze znacznikami: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Pobierz" @@ -706,7 +1120,8 @@ msgid "" msgstr "ProszÄ™ pobrać przeglÄ…darkÄ™, która obsÅ‚uguje \n\tdźwiÄ™k w HTML5, pod adresem <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Oryginalny plik" @@ -714,6 +1129,11 @@ msgstr "Oryginalny plik" msgid "WebM file (Vorbis codec)" msgstr "plik WebM (kodek Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Utworzono" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -724,70 +1144,267 @@ msgstr "plik WebM (kodek Vorbis)" msgid "Image for %(media_title)s" msgstr "Grafika dla %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "Plik PDF" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" -msgstr "" +msgstr "Perspektywa" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" -msgstr "" +msgstr "PoczÄ…tek" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" -msgstr "" +msgstr "Góra" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" -msgstr "" +msgstr "KrawÄ™dź" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" -msgstr "" +msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" -msgstr "" +msgstr "Pobierz model" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" -msgstr "" +msgstr "Format pliku" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" -msgstr "" +msgstr "Wysokość obiektu" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." -msgstr "" +msgstr "Niestety ten materiaÅ‚ nie bÄ™dzie widocznyâŽ, ponieważ twoja przeglÄ…darka nie⎠osbÅ‚uguje formatu HTML5." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" +msgstr "Możesz pobrać porzÄ…dnÄ… przeglÄ…darkÄ™, która jest w stanie odtworzyć ten materiaÅ‚ filmowy, ze strony <a href=\"http://getfirefox.com/\">⎠http://getfirefox.com</a>!" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "Plik WebM (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Tu możesz Å›ledzić stan przetwarzania mediów na tym serwerze." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Przetwarzane media" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Å»adne media nie sÄ… obecnie przetwarzane" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "NIe udaÅ‚o siÄ™ przesÅ‚ać tych plików:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Brak nieprzetworzonych wpisów!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Ostatnie 10 udanych wysyÅ‚ek" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Na razie nie przetworzono żadnego wpisu!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "plik WebM (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Dodaj kolekcjÄ™" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Dodaj swoje media" @@ -806,11 +1423,6 @@ msgstr "%(collection_title)s użytkownika <a href=\"%(user_url)s\">%(username)s< msgid "Edit" msgstr "Edytuj" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "UsuÅ„" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -822,19 +1434,19 @@ msgstr "Na pewno usunąć %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Na pewno usunąć %(media_title)s z %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "UsuÅ„" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 #, python-format msgid "%(username)s's collections" -msgstr "" +msgstr "kolekcja użytkownika %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" -msgstr "" +msgstr "kolekcje użytkownika <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -853,7 +1465,7 @@ msgstr "Media użytkownika %(username)s" msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "pliki użytkownika <a href=\"%(user_url)s\">%(username)s</a> z tagiem <a href=\"%(tag_url)s\">%(tag)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -865,30 +1477,27 @@ msgstr "media użytkownika <a href=\"%(user_url)s\">%(username)s</a>" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– PrzeglÄ…danie mediów użytkownika <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Dodaj komentarz" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Dodaj komentarz" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "na" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "PodglÄ…d komentarza" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Dodane</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Dodano" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 #, python-format msgid "Add “%(media_title)s†to a collection" -msgstr "" +msgstr "Dodaj “%(media_title)s†do kolekcji" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" @@ -907,96 +1516,118 @@ msgstr "Tutaj możesz Å›ledzić stan mediów przesyÅ‚anych do twojej galerii." msgid "Your last 10 successful uploads" msgstr "Ostatnie 10 twoich udanych wysyÅ‚ek" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Profil użytkownika %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Niestety, nie znaleziono takiego użytkownika." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Wymagana weryfikacja adresu e-mail." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Prawie gotowe! Twoje konto oczekuje na aktywacjÄ™." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Za kilka chwil powinieneÅ› otrzymać e-mail z instrukcjami jak to zrobić." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "JeÅ›li nie nadejdzie:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "WyÅ›lij ponownie e-mail weryfikujÄ…cy" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "KtoÅ› zarejestrowaÅ‚ konto o tej nazwie, ale nadal oczekuje ono na aktywacjÄ™." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "JeÅ›li jesteÅ› tÄ… osobÄ…, ale zgubiÅ‚eÅ› swój e-mail weryfikujÄ…cy, to możesz siÄ™ <a href=\"%(login_url)s\">zalogować</a> i wysÅ‚ać go ponownie." +msgid "%(username)s's profile" +msgstr "Profil użytkownika %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "W tym miejscu można siÄ™ przedstawić innym." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Edytuj profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Ten użytkownik nie wypeÅ‚niÅ‚ (jeszcze) opisu swojego profilu." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" -msgstr "" +msgstr "PrzeglÄ…daj kolekcje" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Zobacz wszystkie media użytkownika %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Tu bÄ™dÄ… widoczne twoje media, ale na razie niczego tu jeszcze nie ma." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Tu nie ma jeszcze żadnych mediów..." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Wymagana weryfikacja adresu e-mail." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Prawie gotowe! Twoje konto oczekuje na aktywacjÄ™." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Za kilka chwil powinieneÅ› otrzymać e-mail z instrukcjami jak to zrobić." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "JeÅ›li nie nadejdzie:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "WyÅ›lij ponownie e-mail weryfikujÄ…cy" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "KtoÅ› zarejestrowaÅ‚ konto o tej nazwie, ale nadal oczekuje ono na aktywacjÄ™." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "JeÅ›li jesteÅ› tÄ… osobÄ…, ale zgubiÅ‚eÅ› swój e-mail weryfikujÄ…cy, to możesz siÄ™ <a href=\"%(login_url)s\">zalogować</a> i wysÅ‚ać go ponownie." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" -msgstr "" +msgstr "(usuÅ„)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" -msgstr "" +msgstr "Znajduje siÄ™ w kolekcji " #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "Dodaj do kolekcji" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 @@ -1034,50 +1665,85 @@ msgstr "nowsze" msgid "older" msgstr "starsze" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Znaczniki:" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Nie udaÅ‚o siÄ™ odczytać pliku grafiki." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Ups!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" -msgstr "" +msgstr "WystÄ…piÅ‚ błąd" + +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "NiewÅ‚aÅ›ciwe żądanie" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "Żądanie wysÅ‚ane do serwera jest nieprawidÅ‚owe, sprawdź je proszÄ™ ponownie" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" -msgstr "" +msgstr "Operacja niedozwolona" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" -msgstr "" +msgstr "Misiaczku, nie możesz tego uczynić!</p><p>PróbowaÅ‚eÅ› wykonać dziaÅ‚anie, do którego nie masz uprawnieÅ„. Czy naprawdÄ™ chciaÅ‚eÅ› skasować znowu wszystkie konta?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." -msgstr "" +msgstr "WyglÄ…da na to, że nic tutaj nie ma!</p><p>JeÅ›li jesteÅ› pewny, że adres jest prawidÅ‚owy, być może strona zostaÅ‚a skasowana lub przeniesiona." + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "rok" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "miesiÄ…c" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "tydzieÅ„" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "dzieÅ„" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "godzina" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minuta" #: mediagoblin/user_pages/forms.py:23 msgid "Comment" -msgstr "" +msgstr "Komentarz" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Możesz formatować przy pomocy skÅ‚adni <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a>." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Możesz formatować tekst za pomocÄ… skÅ‚adni <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\"> Markdown</a>." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1089,7 +1755,7 @@ msgstr "Na pewno chcÄ™ usunąć ten element z kolekcji" #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "Kolekcja" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" @@ -1099,73 +1765,84 @@ msgstr "-- wybierz --" msgid "Include a note" msgstr "Dodaj notatkÄ™" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "komentarze do twojego wpisu" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Możesz formatować tekst za pomocÄ… skÅ‚adni\n<a ref=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\nMarkdown</a>." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Komentowanie jest wyłączone." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Ups, twój komentarz nie zawieraÅ‚ treÅ›ci." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Twój komentarz zostaÅ‚ opublikowany!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "Sprawdź swoje wpisy i spróbuj ponownie." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Musisz wybrać lub dodać kolekcjÄ™" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" już obecne w kolekcji \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" dodano do kolekcji \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Media zostaÅ‚y usuniÄ™te." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "Media nie zostaÅ‚y usuniÄ™te ponieważ nie potwierdziÅ‚eÅ›, że jesteÅ› pewien." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Za chwilÄ™ usuniesz media innego użytkownika. Zachowaj ostrożność." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Element zostaÅ‚ usuniÄ™ty z kolekcji." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "Ten element nie zostaÅ‚ usuniÄ™ty, ponieważ nie zaznaczono, że jesteÅ› pewien." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Zamierzasz usunąć element z kolekcji innego użytkownika. Zachowaj ostrożność." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "UsuniÄ™to kolekcjÄ™ \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "Ta kolekcja nie zostaÅ‚a usuniÄ™ta, ponieważ nie zaznaczono, że jesteÅ› pewien." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Zamierzasz usunąć kolekcjÄ™ innego użytkownika. Zachowaj ostrożność." diff --git a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo Binary files differindex af50e027..830dffa2 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 3b2ed203..1bf3ef84 100644 --- a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po @@ -3,16 +3,18 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Rafael Ferreira <rafael.f.f1@gmail.com>, 2013. -# <snd.noise@gmail.com>, 2011. -# ufa <ufa@technotroll.org>, 2011. -# Vinicius SM <viniciussm@rocketmail.com>, 2013. +# osc <snd.noise@gmail.com>, 2013 +# Rafael Ferreira <rafael.f.f1@gmail.com>, 2013 +# osc <snd.noise@gmail.com>, 2011 +# ufa <ufa@technotroll.org>, 2011 +# Canopus, 2013 +# Canopus, 2013 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/mediagoblin/language/pt_BR/)\n" "MIME-Version: 1.0\n" @@ -22,253 +24,264 @@ msgstr "" "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Desculpa, o registro está desativado neste momento." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "Nome de usuário ou email inválido." -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "Este campo não aceita endereços de email." -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "Este campo requer um endereço de email." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Nome de Usuário" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Senha" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Endereço de email" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Nome de usuário ou email" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Desculpa, o registro está desativado neste momento." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Desculpe, um usuário com este nome já existe." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Desculpe, um usuário com esse email já está cadastrado" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "O seu endereço de e-mail foi verificado. Você pode agora fazer login, editar seu perfil, e enviar imagens!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "A chave de verificação ou nome usuário estão incorretos." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Você precisa entrar primeiro para sabermos para quem mandar o email!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Você já verificou seu email!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "O email de verificação foi enviado novamente." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "Não foi possÃvel encontrar alguém com esse nome de usuário." - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Um email foi enviado com instruções para trocar sua senha." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Não foi possÃvel enviar o email de recuperação de senha, pois seu nome de usuário está inativo ou o email da sua conta não foi confirmado." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Agora você pode entrar usando sua nova senha." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "TÃtulo" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Descrição desse trabalho" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Você pode usar\n<a href=\"http://daringfireball.net/projects/markdown/basics\">\nMarkdown</a> para formatação." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Etiquetas" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Separe as etiquetas com vÃrgulas." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Arquivo" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "O arquivo não pode estar vazio" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "A parte do tÃtulo do endereço dessa mÃdia. Geralmente você não precisa mudar isso." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Licença" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Biografia" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Website" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Este endereço contém erros" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Senha antiga" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Digite sua senha antiga para provar que esta conta é sua." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Me enviar um email quando outras pessoas comentarem em minhas mÃdias" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nova senha" +msgid "Enable insite notifications about events." +msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "Licença preferida" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "Esta será sua licença padrão nos formulários de envio." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Me enviar um email quando outras pessoas comentarem em minhas mÃdias" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "O tÃtulo não pode ficar vazio" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Descrição desta coleção" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "A parte do tÃtulo do endereço dessa coleção. Geralmente você não precisa mudar isso." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Senha antiga" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Digite sua senha antiga para provar que esta conta é sua." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nova senha" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Novo endereço de email" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Senha" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Digite sua senha para provar que esta conta é sua." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Uma entrada com esse arquivo já existe para esse usuário" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Você está editando a mÃdia de outro usuário. Tenha cuidado." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "Você adicionou o anexo %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "Você só pode editar o seu próprio perfil." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Você está editando um perfil de usuário. Tenha cuidado." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "As mudanças no perfil foram salvas" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Senha errada" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "As mudanças na conta foram salvas" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "Você precisa confirmar a exclusão da sua conta." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Você já tem uma coleção chamada \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "Já existe uma coleção com este arquivo para este usuário." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Você está editando a coleção de um outro usuário. Prossiga com cuidado." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Seu endereço de email foi verificado." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Senha errada" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Não é possÃvel fazer link de tema... nenhum tema definido\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "Pulando \"%s\"; já configurado.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -276,15 +289,202 @@ msgid "" "domain." msgstr "Cookie CSFR não está presente. Isso é provavelmente o resultado de um bloqueador de cookies ou algo do tipo.<br/>Tenha certeza de autorizar este domÃnio a configurar cookies." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Desculpe, não tenho suporte a este tipo de arquivo :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Conversão do vÃdeo falhou" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "Banir o usuário" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "Enviar uma mensagem ao usuário" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "O usuário será banido até:" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "Por quê você está banindo esse usuário?" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "Aviso de" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "comentou na sua publicação" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "Você se inscreveu nos comentários de %s!" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "Você não irá receber notificações de comentários em %s." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "Desculpe, você atingiu seu limite de envios." + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Nome de Usuário" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Endereço de email" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Nome de usuário ou email" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "Mantenha-me Conectado" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Nome de usuário ou email" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Se esse endereço de email (sensÃvel a maiúsculo/minúsculo!) estiver registrado, um email será enviado com instruções para alterar sua senha." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Não foi possÃvel encontrar alguém com esse nome de usuário." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Um email foi enviado com instruções para trocar sua senha." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Não foi possÃvel enviar o email de recuperação de senha, pois seu nome de usuário está inativo ou o email da sua conta não foi confirmado." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Agora você pode entrar usando sua nova senha." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Sua senha foi alterada com sucesso." + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Defina a sua nova senha" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Definir senha" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Alterando a senha de %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Salvar" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Ainda não tem conta?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Crie uma aqui!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Recuperar senha" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Mandar instruções" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Esqueceu sua senha?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Localização" @@ -294,6 +494,10 @@ msgstr "Localização" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Ver no <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Permitir" @@ -348,7 +552,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "Este campo é necessário para clientes públicos" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "O cliente {0} foi registrado!" @@ -361,223 +565,335 @@ msgid "Your OAuth clients" msgstr "Seus clientes OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Adicionar" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "Desculpe, já existe uma conta associada a esse OpenID." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "Desculpe, o servidor OpenID não pôde ser encontrado" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "Nenhum serviço OpenID encontrado para %s" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Verificação de %s falhou: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Verificação cancelada" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "O endereço do seu OpenID foi salvo com sucesso." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "Esse OpenID não está associado a esta conta." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "OpenID removido com sucesso." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Adicionar um OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Deletar um OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Apagar" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Entrar" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Autenticação falhou" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "Entre para criar uma conta!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "Ou entre com uma senha!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "Ou entre com OpenID!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "Ou registre com OpenID!" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "O endereço de email Persona foi removido com sucesso." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "Esse endereço de email Persona não está associado a esta conta." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "Desculpe, já existe uma conta associada a este endereço de email Persona." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Seu endereço de email Persona foi salvo com sucesso." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "Excluir um endereço de email Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "Adicionar um endereço de email Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "Ou entre com Persona!" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "Ou registre com Persona!" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Arquivo inválido para esse tipo de mÃdia" -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "Falha ao copiar para armazenamento público." + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "Tamanho máximo de arquivo: {0} mb" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Arquivo" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "Você pode usar\n<a href=\"http://daringfireball.net/projects/markdown/basics\">\nMarkdown</a> para formatação." + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Você deve fornecer um arquivo." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Eba! Enviado!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "Coleção \"%s\" adicionada!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Imagem do goblin se estressando" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "até %(until_when)s" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "indefinidamente" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Verifique seu email!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "sair" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Entrar" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "Conta de <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Mudar configurações da conta" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Painel de processamento de mÃdia" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "Sair" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Adicionar mÃdia" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Criar nova coleção" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." -msgstr "" +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "Painel de gerenciamento de usuário" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." -msgstr "Lançado sob a <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Código fonte</a> disponÃvel." - -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Explorar" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Olá, bem-vindo a este site MediaGoblin." - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." -msgstr "Este site roda o <a href=\"http://mediagoblin.org\">MediaGoblin</a>, um programa excelente para hospedar, gerenciar e compartilhar mÃdia." - -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." -msgstr "Para adicionar sua própria mÃdia, publicar comentários e mais outras coisas, você pode entrar com sua conta MediaGoblin." - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" -msgstr " Ainda não tem uma conta? É facil!" - -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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\">Criar uma conta neste site</a>\nou\n<a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Configurar MediaGoblin em seu próprio servidor</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "MÃdia mais recente" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Autorização" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "MÃdia em processo" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "Autorizar" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Nenhuma mÃdia em processo" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Esses envios não foram processados:" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Você está conectado como" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Nenhuma entrada falhou!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "Você quer autorizar" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "Últimos 10 envios bem sucedidos" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Ainda não há entradas processadas!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Defina a sua nova senha" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "um aplicativo desconhecido" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Definir senha" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "para acessar sua conta?" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Recuperar senha" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Aplicativos com acesso à sua conta podem:" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Mandar instruções" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Olá %(username)s,\n\npara alterar sua senha do GNU MediaGoblin, abra a seguinte URL\nno seu navegador web:\n\n%(verification_url)s\n\nSe você acha que isso é um erro, desconsidere esse email e continue sendo um goblin feliz" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Autenticação falhou" +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "Alterar suas informações" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Ainda não tem conta?" +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "Autorização Finalizada" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Crie uma aqui!" +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "Autorização ConcluÃda" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Esqueceu sua senha?" +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Copie e cole isto no seu cliente:" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "Criar uma conta!" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "Criar" @@ -592,6 +908,62 @@ msgid "" "%(verification_url)s" msgstr "Olá %(username)s,\n\nPara ativar sua conta GNU MediaGoblin, visite este endereço no seu navegador:\n\n%(verification_url)s" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "Fornecido pelo <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, um projeto <a href=\"http://gnu.org/\">GNU</a>." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "Lançado sob a <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Código fonte</a> disponÃvel." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "Termos de Serviço" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Explorar" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Olá, bem-vindo a este site MediaGoblin." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "Este site roda o <a href=\"http://mediagoblin.org\">MediaGoblin</a>, um programa excelente para hospedar, gerenciar e compartilhar mÃdia." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "Para adicionar sua própria mÃdia, publicar comentários e mais outras coisas, você pode entrar com sua conta MediaGoblin." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr " Ainda não tem uma conta? É facil!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "\n>Crie uma conta neste site</a>\nou" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n<a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Configure MediaGoblin em seu próprio servidor</a>" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -604,13 +976,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Editando os anexos de %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Anexos" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Adicionar anexo" @@ -627,12 +999,18 @@ msgstr "Cancelar" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Salvar mudanças" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Alterando email de %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -643,7 +1021,7 @@ msgid "Yes, really delete my account" msgstr "Sim, realmente deletar minha conta" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Deletar permanentemente" @@ -660,10 +1038,14 @@ msgstr "Editando %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "Alterando as configurações da conta de %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "Deletar minha conta" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Email" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -675,6 +1057,39 @@ msgstr "Editando %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Editando perfil de %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "Olá,\n\nNós querÃamos verificar que você é %(username)s. Se for esse o caso, então por favor clique no link abaixo para verificar seu novo endereço de email.\n\n%(verification_url)s\n\nSe você não for %(username)s ou se não fez um pedido de alteração do endereço de email, você pode ignorar\nesta mensagem." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Novos comentários" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)s" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Marcar tudo como lido" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -685,8 +1100,8 @@ msgstr "Etiquetas desta mÃdia: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Baixar" @@ -709,7 +1124,8 @@ msgid "" msgstr "Você pode obter um navegador moderno\n »capaz de reproduzir o áudio em <a href=\"http://getfirefox.com\">\n » http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Arquivo original" @@ -717,6 +1133,11 @@ msgstr "Arquivo original" msgid "WebM file (Vorbis codec)" msgstr "Arquivo WebM (codec Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Criado" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -727,70 +1148,267 @@ msgstr "Arquivo WebM (codec Vorbis)" msgid "Image for %(media_title)s" msgstr "Imagem para %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "Alternar Rotação" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "Arquivo PDF" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "Perspectiva" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "Frente" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "Cima" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "Lado" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "Baixar o modelo" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "Formato de Arquivo" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "Altura do Objeto" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "Desculpe, este vÃdeo não irá reproduzir porque\n seu navegador não suporta vÃdeo\n HTML5." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "Você pode obter um navegador moderno\n capaz de reproduzir este vÃdeo em <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "Arquivo WebM (640p, VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "Arquivo WebM (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "MÃdia em processo" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Nenhuma mÃdia em processo" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Esses envios não foram processados:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Nenhuma entrada falhou!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Últimos 10 envios bem sucedidos" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Ainda não há entradas processadas!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "Motivo" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "Painel de usuário" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "Usuários Ativos" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "Nenhum usuário encontrado." #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Adicionar uma coleção" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Adicionar sua mÃdia" @@ -809,11 +1427,6 @@ msgstr "%(collection_title)s de <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "Editar" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Apagar" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -825,7 +1438,7 @@ msgstr "Realmente apagar %(title)s ?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Realmente remover %(media_title)s de %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Apagar" @@ -856,7 +1469,7 @@ msgstr "MÃdia de %(username)s's" msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "MÃdias de <a href=\"%(user_url)s\">%(username)s</a> com a etiqueta <a href=\"%(tag_url)s\">%(tag)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -868,24 +1481,21 @@ msgstr "MÃdia de <a href=\"%(user_url)s\"> %(username)s </a> " msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Vendo mÃdia de <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Adicionar um comentário" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Adicionar este comentário" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "em" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Pré-visualização do comentário" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Adicionado em</h3>\n<p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Adicionado há" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -910,84 +1520,106 @@ msgstr "Você pode verificar como a mÃdia esta sendo processada para sua galeri msgid "Your last 10 successful uploads" msgstr "Seus últimos 10 envios bem sucedidos" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Perfil de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Desculpe, esse usuário não foi encontrado." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Verificação de email necessária" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Quase pronto! Sua conta ainda precisa ser ativada." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Um email deve chegar em instantes com instruções de como fazê-lo." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Caso contrário:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Reenviar email de verificação" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "\nâ– Publicado por <a href=\"%(user_url)s\"\nclass=\"comment_authorlink\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Alguém registrou uma conta com esse nome de usuário, mas ainda precisa ser ativada." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Se você é essa pessoa, mas você perdeu seu e-mail de verificação, você pode <a href=\"%(login_url)s\">efetuar login</a> e reenviá-la." +msgid "%(username)s's profile" +msgstr "Perfil de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Aqui é o lugar onde você fala de si para os outros." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Editar perfil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Esse usuário não preencheu seu perfil (ainda)." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "Ver coleções" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Ver todas as mÃdias de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Aqui é onde sua mÃdia vai aparecer, mas parece que você não adicionou nada ainda." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." -msgstr "Aparentemente não há nenhuma mÃdia aqui ainda..." +msgstr "Parece que ainda não há nenhuma mÃdia por aqui..." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Verificação de email necessária" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Quase pronto! Sua conta ainda precisa ser ativada." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Um email deve chegar em instantes com instruções de como fazê-lo." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Caso contrário:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Reenviar email de verificação" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Alguém registrou uma conta com esse nome de usuário, mas ainda precisa ser ativada." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Se você é essa pessoa, mas você perdeu seu e-mail de verificação, você pode <a href=\"%(login_url)s\">efetuar login</a> e reenviá-la." #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" @@ -995,11 +1627,11 @@ msgstr "(apagar)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" -msgstr "" +msgstr "Colecionado em" #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "Adicionar a uma coleção" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 @@ -1030,57 +1662,92 @@ msgstr "Ir a página:" #: mediagoblin/templates/mediagoblin/utils/prev_next.html:28 #: mediagoblin/templates/mediagoblin/utils/prev_next.html:33 msgid "newer" -msgstr "mais nova" +msgstr "mais recente" #: mediagoblin/templates/mediagoblin/utils/prev_next.html:39 #: mediagoblin/templates/mediagoblin/utils/prev_next.html:44 msgid "older" msgstr "mais antiga" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Etiquetas" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Não foi possÃvel ler o arquivo de imagem." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Oops" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Um erro ocorreu" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "Operação não permitida" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "Me desculpe Dave, não posso deixar você fazer isso!</p><p>Você tentou executar uma função sem autorização. Por acaso estava novamente tentando deletar todas as contas de usuários?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "Parece que não há uma página com este endereço. Desculpe!</p><p>Se você tem certeza que este endereço está correto, talvez a página que esteja procurando tenha sido movida ou deletada." +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "ano" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "mês" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "semana" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "dia" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "hora" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minuto" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "Comentário" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Você pode usar <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> para formatação." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Você pode usar <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Markdown</a> para formatação." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1096,79 +1763,90 @@ msgstr "Coleção" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" -msgstr "" +msgstr "-- Selecionar --" #: mediagoblin/user_pages/forms.py:42 msgid "Include a note" msgstr "Incluir uma nota" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "comentou na sua publicação" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Você pode usar\n<a href=\"http://daringfireball.net/projects/markdown/basics\">\nMarkdown</a> para formatação de texto." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Desculpe, os comentários estão desabilitados." + +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Ops, seu comentário estava vazio." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Seu comentário foi postado!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." -msgstr "" +msgstr "Por favor, verifique suas entradas e tente novamente." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Você deve selecionar ou adicionar uma coleção" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" já está na coleção \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" adicionado à coleção \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Você deletou a mÃdia." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "A mÃdia não foi apagada porque você não marcou que tinha certeza." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Você vai apagar uma mÃdia de outro usuário. Tenha cuidado." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Você deletou o item da coleção." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "O item não foi apagado porque você não marcou que tinha certeza." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Você está prestes a remover um item da coleção de um outro usuário. Prossiga com cuidado." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Você deletou a coleção \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "A coleção não foi apagada porque você não marcou que tinha certeza." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Você está prestes a deletar a coleção de um outro usuário. Prossiga com cuidado." diff --git a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo Binary files differindex 62cbf028..d516f5ce 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 da585d5c..80d7afb3 100644 --- a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po @@ -3,15 +3,15 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <gapop@hotmail.com>, 2011. -# George Pop <gapop@hotmail.com>, 2011-2013. +# George Pop <gapop@hotmail.com>, 2011 +# George Pop <gapop@hotmail.com>, 2011-2013 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-10 04:13+0000\n" -"Last-Translator: George Pop <gapop@hotmail.com>\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: Romanian (http://www.transifex.com/projects/p/mediagoblin/language/ro/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -20,253 +20,264 @@ msgstr "" "Language: ro\n" "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Ne pare rău, dar înscrierile sunt dezactivate pe acest server." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "Nume de utilizator sau adresă de e-mail nevalidă." -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "Această rubrică nu este pentru adrese de e-mail." -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "Această rubrică trebuie completată cu o adresă de e-mail." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Nume de utilizator" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Parolă" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Adresa de e-mail" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Numele de utilizator sau adresa de e-mail" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Ne pare rău, dar înscrierile sunt dezactivate pe acest server." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Ne pare rău, există deja un utilizator cu acelaÈ™i nume." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Există deja un utilizator înregistrat cu această adresă de e-mail." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 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 verificată. PoÈ›i să te autentifici, să îți completezi profilul È™i să trimiÈ›i imagini!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Cheie de verificare sau user ID incorect." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Trebuie să fii autentificat ca să È™tim cui să trimitem mesajul!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Adresa ta de e-mail a fost deja verificată!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "E-mail-ul de verificare a fost retrimis." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "Dacă adresa de e-mail este în baza noastră de date, atunci se va trimite imediat un mesaj cu instrucÈ›iuni pentru schimbarea parolei. ÈšineÈ›i cont de litere mari / litere mici la introducerea adresei!" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "Nu există nimeni cu acest nume de utilizator." - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "S-a trimis un e-mail cu instrucÈ›iuni pentru schimbarea parolei." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "E-mailul pentru recuperarea parolei nu a putut fi trimis deoarece contul tău e inactiv sau adresa ta de e-mail nu a fost verificată." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Acum te poÈ›i autentifica cu noua parolă." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titlu" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Descrierea acestui fiÈ™ier" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "PoÈ›i folosi\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> pentru formatare." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Cuvinte-cheie" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Desparte cuvintele-cheie prin virgulă." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Identificator" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "Identificatorul nu poate să lipsească" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Partea corespunzătoare titlului din adresa acestui fiÈ™ier media. De regulă poate fi lăsată nemodificată." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "LicenÈ›a" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Biografie" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Sit Web" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Această adresă prezintă erori" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Vechea parolă" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Introdu vechea parolă pentru a demonstra că eÈ™ti titularul acestui cont." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Trimite-mi un e-mail când alÈ›ii comentează fiÈ™ierele mele" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Noua parolă" +msgid "Enable insite notifications about events." +msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "LicenÈ›a preferată" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "Aceasta va fi licenÈ›a implicită pe formularele de upload." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Trimite-mi un e-mail când alÈ›ii comentează fiÈ™ierele mele" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "Titlul nu poate să fie gol" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Descriere pentru această colecÈ›ie" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "Partea din adresa acestei colecÈ›ii care corespunde titlului. De regulă nu e necesar să faci o modificare." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Vechea parolă" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Introdu vechea parolă pentru a demonstra că eÈ™ti titularul acestui cont." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Noua parolă" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Parolă" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Există deja un entry cu acelaÈ™i identificator pentru acest utilizator." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Editezi fiÈ™ierul unui alt utilizator. Se recomandă prudență." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "Ai anexat %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "Nu poÈ›i modifica decât propriul tău profil." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Editezi profilul unui utilizator. Se recomandă prudență." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Modificările profilului au fost salvate" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Parolă incorectă" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Setările pentru acest cont au fost salvate" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "Trebuie să confirmi È™tergerea contului tău." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Ai deja o colecÈ›ie numită \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "O colecÈ›ie cu acelaÈ™i slug există deja pentru acest utilizator." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Lucrezi pe colecÈ›ia unui alt utilizator. Se recomandă prudență." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Parolă incorectă" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Tema nu poate fi ataÈ™ată... nu există o temă selectată\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "Nu există un folder de elemente pentru această temă\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "A fost însă găsit un symlink către vechiul folder; s-a È™ters.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "Nu s-a putut crea link pentru \"%s\": %s există deja È™i nu este symlink\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "S-a omis \"%s\"; configurat deja.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "Există deja un link pentru \"%s\"; va fi È™ters.\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -274,15 +285,202 @@ msgid "" "domain." msgstr "LipseÈ™te cookie-ul CSRF. Probabil că blocaÈ›i cookie-urile.<br/>AsiguraÈ›i-vă că există permisiunea setării cookie-urilor pentru acest domeniu." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Scuze, nu recunosc acest tip de fiÈ™ier :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "unoconv nu poate fi executat; verificaÈ›i log-ul" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Transcodarea video a eÈ™uat" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "a făcut un comentariu la postarea ta" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Nume de utilizator" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Adresa de e-mail" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Numele de utilizator sau adresa de e-mail" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Numele de utilizator sau adresa de e-mail" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Dacă adresa de e-mail este în baza noastră de date, atunci se va trimite imediat un mesaj cu instrucÈ›iuni pentru schimbarea parolei. ÈšineÈ›i cont de litere mari / litere mici la introducerea adresei!" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Nu există nimeni cu acest nume de utilizator." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "S-a trimis un e-mail cu instrucÈ›iuni pentru schimbarea parolei." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "E-mailul pentru recuperarea parolei nu a putut fi trimis deoarece contul tău e inactiv sau adresa ta de e-mail nu a fost verificată." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Acum te poÈ›i autentifica cu noua parolă." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Parola a fost schimbată cu succes" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "StabileÈ™te noua parolă" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "StabileÈ™te parola" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Se modifică parola pentru %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Salvează" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Nu ai un cont?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Creează-l aici!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Recuperează parola" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Trimite instrucÈ›iuni" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Ai uitat parola?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Locul" @@ -292,6 +490,10 @@ msgstr "Locul" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Vezi pe <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Permite" @@ -346,7 +548,7 @@ msgstr "URI-ul de redirectare pentru aplicaÈ›ii, această rubrică\n msgid "This field is required for public clients" msgstr "Această rubrică este obligatorie pentru clienÈ›ii publici" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Clientul {0} a fost înregistrat!" @@ -359,88 +561,357 @@ msgid "Your OAuth clients" msgstr "ClienÈ›ii tăi OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Adaugă" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Șterge" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Autentificare" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Autentificare eÈ™uată!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Formatul fiÈ™ierului nu corespunde cu tipul de media selectat." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "FiÈ™ier" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Trebuie să selectezi un fiÈ™ier." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Ura! Trimis!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "ColecÈ›ia \"%s\" a fost creată!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Imagine cu un goblin stresat" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Verifică adresa de e-mail!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "IeÈ™ire" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Autentificare" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "Contul lui <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Modifică setările contului" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Panou de procesare media" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "IeÈ™ire" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Trimite fiÈ™ier" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Creează colecÈ›ie nouă" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Cele mai recente fiÈ™iere" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Creează un cont!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Creează" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Bună, %(username)s,\n\npentru activarea contului tău la GNU MediaGoblin, accesează adresa următoare:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." msgstr "Construit cu <a href=\"http://mediagoblin.org/\" title='Versiunea %(version)s'>MediaGoblin</a>, un proiect <a href=\"http://gnu.org/\">GNU</a>." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -448,147 +919,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Publicat sub licenÈ›a <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Codul sursă</a> este disponibil." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "Imagine cu un goblin stresat" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "Explorează" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Salut, bine ai venit pe acest site MediaGoblin!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 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:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Pentru a adăuga fiÈ™ierele tale È™i pentru a comenta te poÈ›i autentifica cu contul tău MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "ÃŽncă nu ai unul? E simplu!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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 serverul tău</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Cele mai recente fiÈ™iere" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Aici poÈ›i urmări starea fiÈ™ierelor aflate în curs de procesare pe acest server." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "FiÈ™iere în curs de procesare" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Niciun fiÈ™ier în curs de procesare" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Aceste fiÈ™iere nu au putut fi procesate:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Niciun entry cu erori!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "Ultimele 10 upload-uri reuÈ™ite" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Nu există încă niciun entry procesat!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "StabileÈ™te noua parolă" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "StabileÈ™te parola" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Recuperează parola" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Trimite instrucÈ›iuni" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Hi %(username)s,\n" "\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Bună, %(username)s\n\nPentru a schimba parola ta la GNU MediaGoblin, accesează adresa următoare:\n\n%(verification_url)s\n\nDacă ai primit acest mesaj din greÈ™eală, ignoră-l È™i fii mai departe un goblin fericit!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Autentificare eÈ™uată!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Nu ai un cont?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Creează-l aici!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Ai uitat parola?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Creează un cont!" - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Creează" +" >Create an account at this site</a>\n" +" or" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" -"\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" "\n" -"%(verification_url)s" -msgstr "Bună, %(username)s,\n\npentru activarea contului tău la GNU MediaGoblin, accesează adresa următoare:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -602,13 +972,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Editare anexe la %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Anexe" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "AtaÈ™ează" @@ -625,12 +995,18 @@ msgstr "Anulare" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Salvează modificările" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -641,7 +1017,7 @@ msgid "Yes, really delete my account" msgstr "Da, doresc È™tergerea contului meu" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Șterge definitiv" @@ -658,10 +1034,14 @@ msgstr "Editare %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "Se modifică setările contului pentru userul %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "Șterge contul meu" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -673,6 +1053,39 @@ msgstr "Editare %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Editare profil %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "în urmă cu %(formatted_time)s" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -683,8 +1096,8 @@ msgstr "FiÈ™ier etichetat cu cuvintele-cheie: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Download" @@ -707,7 +1120,8 @@ msgid "" msgstr "PoÈ›i lua un browser modern \n\tcapabil să redea această înregistrare de la <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "FiÈ™ierul original" @@ -715,6 +1129,11 @@ msgstr "FiÈ™ierul original" msgid "WebM file (Vorbis codec)" msgstr "FiÈ™ier WebM (codec Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Creat" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,70 +1144,267 @@ msgstr "FiÈ™ier WebM (codec Vorbis)" msgid "Image for %(media_title)s" msgstr "Imagine pentru %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "Rotire" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "FiÈ™ier PDF" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "Perspectivă" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "Din față" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "De sus" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "Lateral" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "Descarcă modelul" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "Formatul fiÈ™ierului" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "ÃŽnălÈ›imea obiectului" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "Ne pare rău, dar această înregistrare video nu va funcÈ›iona deoarece browser-ul dvs. nu este compatibil cu HTML5 video." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "PuteÈ›i obÈ›ine un browser Web modern care poate reda această înregistrare de la <a href=\"http://getfirefox.com\">http://getfirefox.com</a>!" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "FiÈ™ier WebM (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Aici poÈ›i urmări starea fiÈ™ierelor aflate în curs de procesare pe acest server." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "FiÈ™iere în curs de procesare" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Niciun fiÈ™ier în curs de procesare" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Aceste fiÈ™iere nu au putut fi procesate:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Niciun entry cu erori!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Ultimele 10 upload-uri reuÈ™ite" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Nu există încă niciun entry procesat!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Creează o colecÈ›ie" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Adaugă fiÈ™ierele tale media" @@ -807,11 +1423,6 @@ msgstr "%(collection_title)s de <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "Editare" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Șterge" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,7 +1434,7 @@ msgstr "Sigur doreÈ™ti să È™tergi %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Sigur doreÈ™ti să È™tergi %(media_title)s din %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Șterge" @@ -866,24 +1477,21 @@ msgstr "FiÈ™ierele media ale lui <a href=\"%(user_url)s\">%(username)s</a>" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "<p>â– FiÈ™ierele media ale lui <a href=\"%(user_url)s\">%(username)s</a></p>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Adaugă un comentariu" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Trimite acest comentariu" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "la" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Adăugat la</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Adăugat" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -908,85 +1516,107 @@ msgstr "Aici poÈ›i urmări stadiul procesării fiÈ™ierelor media din galeria ta. msgid "Your last 10 successful uploads" msgstr "Ultimele tale 10 upload-uri reuÈ™ite" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Profil %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Ne pare rău, nu am găsit utilizatorul căutat." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Este necesară verificarea adresei de e-mail" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Aproape gata! Mai trebuie doar să activezi contul." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Vei primi în scurt timp un e-mail cu instrucÈ›iuni." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Dacă nu-l primeÈ™ti:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Retrimite mesajul de verificare" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Cineva a înregistrat un cont cu acest nume de utilizator, dar contul nu a fost încă activat." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Dacă tu eÈ™ti persoana respectivă È™i nu mai ai e-mail-ul de verificare, poÈ›i să te <a href=\"%(login_url)s\">autentifici</a> pentru a-l retrimite." +msgid "%(username)s's profile" +msgstr "Profil %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Aici poÈ›i spune altora ceva despre tine." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Editare profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Acest utilizator nu È™i-a completat (încă) profilul." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "Vizitează colecÈ›iile" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Vezi toate fiÈ™ierele media ale lui %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Aici vor apărea fiÈ™ierele tale media, dar se pare că încă nu ai trimis nimic." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Nu pare să existe niciun fiÈ™ier media deocamdată..." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Este necesară verificarea adresei de e-mail" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Aproape gata! Mai trebuie doar să activezi contul." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Vei primi în scurt timp un e-mail cu instrucÈ›iuni." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Dacă nu-l primeÈ™ti:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Retrimite mesajul de verificare" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Cineva a înregistrat un cont cu acest nume de utilizator, dar contul nu a fost încă activat." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Dacă tu eÈ™ti persoana respectivă È™i nu mai ai e-mail-ul de verificare, poÈ›i să te <a href=\"%(login_url)s\">autentifici</a> pentru a-l retrimite." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "(È™terge)" @@ -1035,50 +1665,85 @@ msgstr "mai noi" msgid "older" msgstr "mai vechi" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Etichetat cu cuvintele-cheie" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "FiÈ™ierul cu imaginea nu a putut fi citit." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Hopa!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "S-a produs o eroare" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "OperaÈ›ia nu este permisă" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "ÃŽmi pare rău, Dave, nu te pot lăsa să faci asta!</p><p>Ai încercat să faci o operaÈ›ie nepermisă. Ai încercat iar să È™tergi toate conturile utilizatorilor?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "Nu există nicio pagină la această adresă.</p><p>Dacă sunteÈ›i sigur că adresa este corectă, poate că pagina pe care o căutaÈ›i a fost mutată sau È™tearsă." +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "anul" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "luna" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "săptămâna" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "ziua" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "ora" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minutul" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "Comentariu" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "PoÈ›i folosi <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> pentru formatare." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1100,73 +1765,84 @@ msgstr "-- Selectează --" msgid "Include a note" msgstr "Adaugă o notiță" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "a făcut un comentariu la postarea ta" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Comentariile sunt dezactivate." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Hopa, ai uitat să scrii comentariul." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Comentariul tău a fost trimis!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "Verifică datele È™i încearcă din nou." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Trebuie să alegi sau să creezi o colecÈ›ie" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" este deja în colecÈ›ia \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" a fost adăugat la colecÈ›ia \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Ai È™ters acest fiÈ™ier" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "FiÈ™ierul nu a fost È™ters deoarece nu ai confirmat că eÈ™ti sigur." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Urmează să È™tergi fiÈ™ierele media ale unui alt utilizator. Se recomandă prudență." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Ai È™ters acest articol din colecÈ›ie." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "Articolul nu a fost È™ters pentru că nu ai confirmat că eÈ™ti sigur(ă)." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Urmează să È™tergi un articol din colecÈ›ia unui alt utilizator. Se recomandă prudență." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Ai È™ters colecÈ›ia \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "ColecÈ›ia nu a fost È™tearsă pentru că nu ai confirmat că eÈ™ti sigur(ă)." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Urmează să È™tergi colecÈ›ia unui alt utilizator. Se recomandă prudență." diff --git a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo Binary files differindex 759f5337..d2c5c02f 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 0dc099ed..9cd7b221 100644 --- a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po @@ -3,16 +3,17 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <deletesoftware@yandex.ru>, 2013. -# <deletesoftware@yandex.ru>, 2011-2012. +# aleksejrs <deletesoftware@yandex.ru>, 2013 +# aleksejrs <deletesoftware@yandex.ru>, 2011-2012 +# Yury Sakarinen, 2013 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-10 15:35+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-02 09:28-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Russian (http://www.transifex.com/projects/p/mediagoblin/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -20,253 +21,264 @@ msgstr "" "Language: ru\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Извините, на Ñтом Ñайте региÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð·Ð°Ð¿Ñ€ÐµÑ‰ÐµÐ½Ð°." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "Извините, Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð½Ð° Ñтом Ñайте отключена." + +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "Ðеправильное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Ð°Ð´Ñ€ÐµÑ Ñлектронной почты." + +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "Ðто поле не Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑа Ñлектронной почты." -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "Ðто поле — Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑа Ñлектронной почты." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Логин" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Пароль" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "ÐÐ´Ñ€ÐµÑ Ñлектронной почты" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Ð°Ð´Ñ€ÐµÑ Ñлектронной почты" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Извините, на Ñтом Ñайте региÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð·Ð°Ð¿Ñ€ÐµÑ‰ÐµÐ½Ð°." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Извините, пользователь Ñ Ñтим именем уже зарегиÑтрирован." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Сожалеем, но на Ñтот Ð°Ð´Ñ€ÐµÑ Ñлектронной почты уже зарегиÑтрирована Ð´Ñ€ÑƒÐ³Ð°Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты потвержден. Ð’Ñ‹ теперь можете войти и начать редактировать Ñвой профиль и загружать новые изображениÑ!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Ðеверный ключ проверки или идентификатор пользователÑ" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Вам надо предÑтавитьÑÑ, чтобы мы знали, кому отправлÑть Ñообщение!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Ð’Ñ‹ уже потвердили Ñвой Ð°Ð´Ñ€ÐµÑ Ñлектронной почты!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." -msgstr "ПереÑлать Ñообщение Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸ÐµÐ¼ аккаунта." +msgstr "Отправить заново Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° подтверждение по е-мÑйл." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "ЕÑли Ñ Ñтим адреÑом Ñлектронной почты (Ñравниваемым чувÑтвительно к региÑтру Ñимволов!) еÑть ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ, то на него отправлено Ñообщение Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñми о том, как Ñменить пароль." - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "Ðе найдено никого Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем пользователÑ." - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Вам отправлено Ñлектронное пиÑьмо Ñ Ð¸Ð½ÑтрукциÑми по Ñмене паролÑ." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Мы не можем отправить Ñообщение Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ, потому что ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ неактивна, либо указанный в ней Ð°Ð´Ñ€ÐµÑ Ñлектронной почты не был подтверждён." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Теперь вы можете войти, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²Ð°Ñˆ новый пароль." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Ðазвание" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "ОпиÑание Ñтого произведениÑ" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Ð”Ð»Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‚ÐºÐ¸ можете иÑпользовать Ñзык\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a>." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Метки" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "(через запÑтую)" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа необходима" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "ЧаÑть адреÑа Ñтого файла, Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð½Ð°Ñ Ð¾Ñ‚ его названиÑ. Её обычно не требуетÑÑ Ð¸Ð·Ð¼ÐµÐ½Ñть." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "ЛицензиÑ" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "БиографиÑ" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Сайт" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Ðтот Ð°Ð´Ñ€ÐµÑ Ñодержит ошибки" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Старый пароль" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Введите Ñвой Ñтарый пароль в качеÑтве доказательÑтва, что Ñто ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "УведомлÑть Ð¼ÐµÐ½Ñ Ð¿Ð¾ e-mail о комментариÑÑ… к моим файлам" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Ðовый пароль" +msgid "Enable insite notifications about events." +msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "ÐŸÑ€ÐµÐ´Ð¿Ð¾Ñ‡Ð¸Ñ‚Ð°ÐµÐ¼Ð°Ñ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "Она будет лицензией по умолчанию Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… загрузок" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "УведомлÑть Ð¼ÐµÐ½Ñ Ð¿Ð¾ e-mail о комментариÑÑ… к моим файлам" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "Ðазвание не может быть пуÑтым" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "ОпиÑание Ñтой коллекции" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа Ñтой коллекции, оÑÐ½Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð½Ð° названии. Обычно не нужно её изменÑть." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Старый пароль" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Введите Ñвой Ñтарый пароль в качеÑтве доказательÑтва, что Ñто ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Ðовый пароль" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Ðовый Ð°Ð´Ñ€ÐµÑ Ñлектронной почты" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Пароль" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Введите Ñвой пароль в качеÑтве доказательÑтва, что Ñто ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "У Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ еÑть файл Ñ Ñ‚Ð°ÐºÐ¾Ð¹ отличительной чаÑтью адреÑа." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Ð’Ñ‹ редактируете файлы другого пользователÑ. Будьте оÑторожны." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "Ð’Ñ‹ добавили ÑопутÑтвующий файл %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "Ð’Ñ‹ можете редактировать только Ñвой ÑобÑтвенный профиль." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Ð’Ñ‹ редактируете профиль пользователÑ. Будьте оÑторожны." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ Ñохранены" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Ðеправильный пароль" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "ÐаÑтройки учётной запиÑи запиÑаны" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "Вам нужно подтвердить, что вы хотите удалить Ñвою учётную запиÑÑŒ." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "У Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑть ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸ÐµÐ¼ «%s»!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "У Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ еÑть ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñ Ñ‚Ð°ÐºÐ¾Ð¹ отличительной чаÑтью адреÑа." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Ð’Ñ‹ редактируете коллекцию другого пользователÑ. Будьте оÑторожны." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты удоÑтоверен." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Ðеправильный пароль" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Ðевозможно привÑзать тему… не выбрано ÑущеÑтвующей темы\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "У Ñтой темы отÑутÑтвует каталог Ñ Ñлементами оформлениÑ\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "Однако найдена (и удалена) ÑÑ‚Ð°Ñ€Ð°Ñ ÑимволичеÑÐºÐ°Ñ ÑÑылка на каталог.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -274,15 +286,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Увы, Ñ Ð½Ðµ поддерживаю Ñтот тип файлов :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Перекодировка видео не удалаÑÑŒ" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "Забанить Ñтого пользователÑ" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "Предупреждение от" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "оÑтавил комментарий к вашему файлу" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "ÐÐ´Ñ€ÐµÑ Ñлектронной почты" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Ð°Ð´Ñ€ÐµÑ Ñлектронной почты" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Ð°Ð´Ñ€ÐµÑ Ñлектронной почты" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "ЕÑли Ñ Ñтим адреÑом Ñлектронной почты (Ñравниваемым чувÑтвительно к региÑтру Ñимволов!) еÑть ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ, то на него отправлено Ñообщение Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñми о том, как Ñменить пароль." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Ðе найдено никого Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем пользователÑ." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Вам отправлено Ñлектронное пиÑьмо Ñ Ð¸Ð½ÑтрукциÑми по Ñмене паролÑ." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Мы не можем отправить Ñообщение Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ, потому что ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ неактивна, либо указанный в ней Ð°Ð´Ñ€ÐµÑ Ñлектронной почты не был подтверждён." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "ID Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¾ неверно." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Теперь вы можете войти, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²Ð°Ñˆ новый пароль." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Ваш пароль Ñменён уÑпешно" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Введите Ñвой новый пароль" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "УÑтановить пароль" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Смена Ð¿Ð°Ñ€Ð¾Ð»Ñ %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Сохранить" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Ðет аккаунта?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Создайте здеÑÑŒ!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Отправить инÑтрукцию" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Забыли Ñвой пароль?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Ðа карте" @@ -292,17 +491,21 @@ msgstr "Ðа карте" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "ПоÑмотреть на <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" -msgstr "" +msgstr "Разрешить" #: mediagoblin/plugins/oauth/forms.py:30 msgid "Deny" -msgstr "" +msgstr "Запретить" #: mediagoblin/plugins/oauth/forms.py:34 msgid "Name" -msgstr "" +msgstr "ИмÑ" #: mediagoblin/plugins/oauth/forms.py:35 msgid "The name of the OAuth client" @@ -346,7 +549,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Клиент {0} зарегиÑтрирован!" @@ -359,88 +562,357 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Добавить" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Добавить OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Удалить OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Удалить" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Войти" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½ÐµÑƒÑпешна!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "Сожалеем, но у Ð½Ð°Ñ ÑƒÐ¶Ðµ еÑть ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ Ñ Ñтим email-адреÑом Persona ." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Ðеправильный формат файла." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Файл" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Ð’Ñ‹ должны загрузить файл." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Ура! Файл загружен!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Â«%s» добавлена!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Изображение нервничающего гоблина" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Подтвердите ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "завершение ÑеанÑа" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Войти" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Изменить наÑтройки учётной запиÑи" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Панель обработки файлов" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "Завершение ÑеанÑа" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Добавить файлы" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Создать новую коллекцию" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Самые новые файлы" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "ÐŸÑ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ Ð´Ð¾Ñтупом к вашей учётной запиÑи могут:" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "загружать файлы от вашего имени" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "ПоÑмотреть личную информацию (напр. профиль, файлы и Ñ‚.д.)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Создайте аккаунт!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Создать" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Привет, %(username)s!\n\nЧтобы активировать Ñвой аккаунт в GNU MediaGoblin, откройте в Ñвоём вебâ€Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ðµ Ñледующую ÑÑылку:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." msgstr "Работает на <a href=\"http://mediagoblin.org/\" title='ВерÑии %(version)s'>MediaGoblin</a>, проекте <a href=\"http://gnu.org/\">GNU</a>." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -448,147 +920,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Он опубликован на уÑловиÑÑ… <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. ДоÑтупны <a href=\"%(source_link)s\">иÑходные текÑты</a>." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "Изображение нервничающего гоблина" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "УÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ÑпользованиÑ" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "Смотреть" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Привет! Добро пожаловать на наш MediaGoblin’овый Ñайт!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 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:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Ð”Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑобÑтвенных файлов, ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ Ñ‚. п. вы можете предÑтавитьÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ вашей MediaGoblin’овой учётной запиÑи." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "У Ð²Ð°Ñ ÐµÑ‘ ещё нет? Ðе проблема!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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:47 -msgid "Most recent media" -msgstr "Самые новые файлы" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "ЗдеÑÑŒ вы можете Ñледить за ÑоÑтоÑнием обработки файлов Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ Ñайта." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Обработка файлов в процеÑÑе" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Ðету файлов Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Обработка Ñтих файлов вызвала ошибку:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "ÐеудавшихÑÑ Ð·Ð°Ð´Ð°Ñ‡ нет!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "ПоÑледние 10 удавшихÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¾Ðº" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Выполненных задач пока нет!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Введите Ñвой новый пароль" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "УÑтановить пароль" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Отправить инÑтрукцию" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" "\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Привет, %(username)s,\n\nчтобы Ñменить Ñвой пароль от GNU MediaGoblin, откройте\nÑледующий URL вашим вебâ€Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð¾Ð¼:\n\n%(verification_url)s\n\nЕÑли вы думаете, что Ñто какаÑâ€Ñ‚о ошибка, то игнорируйте\nÑто Ñообщение и продолжайте быть ÑчаÑтливым гоблином!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½ÐµÑƒÑпешна!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Ещё нету аккаунта?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Создайте здеÑÑŒ!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Забыли Ñвой пароль?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Создать аккаунт!" - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Создать" +" >Create an account at this site</a>\n" +" or" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" -"\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" "\n" -"%(verification_url)s" -msgstr "Привет, %(username)s!\n\nЧтобы активировать Ñвой аккаунт в GNU MediaGoblin, откройте в Ñвоём вебâ€Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ðµ Ñледующую ÑÑылку:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -602,13 +973,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Добавление ÑопутÑтвующего файла Ð´Ð»Ñ %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "СопутÑтвующие файлы" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Добавить ÑопутÑтвующий файл" @@ -625,12 +996,18 @@ msgstr "Отмена" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Сохранить изменениÑ" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -641,7 +1018,7 @@ msgid "Yes, really delete my account" msgstr "Да, на Ñамом деле удалить мою учётную запиÑÑŒ" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Удалить безвозвратно" @@ -658,10 +1035,14 @@ msgstr "Редактирование %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "ÐаÑтройка учётной запиÑи %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "Удалить мою учётную запиÑÑŒ" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Е-майл " + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -673,6 +1054,39 @@ msgstr "Редактирование %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Редактирование Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Ðовые комментарии" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)s назад" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Отметить вÑе, как прочтенные" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -683,8 +1097,8 @@ msgstr "Файлы Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Скачать" @@ -707,7 +1121,8 @@ msgid "" msgstr "Ð’Ñ‹ можете Ñкачать Ñовременный браузер, \n\tÑпоÑобный проиграть Ñто аудио, Ñ <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "ИÑходный файл" @@ -715,6 +1130,11 @@ msgstr "ИÑходный файл" msgid "WebM file (Vorbis codec)" msgstr "WebMâ€Ñ„айл (кодек — Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Создан" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,70 +1145,395 @@ msgstr "WebMâ€Ñ„айл (кодек — Vorbis)" msgid "Image for %(media_title)s" msgstr "Изображение «%(media_title)s»" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF-файл" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "ПерÑпектива" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "Спереди" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "Сверху" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "Сбоку" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "Скачать модель" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "Формат файла" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "Ð’Ñ‹Ñота объекта" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "Сожалеем, Ñтот ролик не проиграетÑÑ, âŽ\nпотому что ваш браузер не поддерживает âŽ\nвидео в ÑоответÑтвии Ñо Ñтандартом HTML5." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "Ð’Ñ‹ можете Ñкачать Ñовременный браузер, ÑпоÑобный воÑпроизводить Ñто видео, Ñ <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "WebM-файл (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "WebM файл (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "ЗдеÑÑŒ вы можете Ñледить за ÑоÑтоÑнием обработки файлов Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ Ñайта." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Обработка файлов в процеÑÑе" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Ðету файлов Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Обработка Ñтих файлов вызвала ошибку:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "ÐеудавшихÑÑ Ð·Ð°Ð´Ð°Ñ‡ нет!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "ПоÑледние 10 удавшихÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¾Ðº" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Выполненных задач пока нет!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +#: mediagoblin/templates/mediagoblin/moderation/user.html:128 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:23 +#, python-format +msgid "User: %(username)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:39 +msgid "Sorry, no such user found." +msgstr "Извините, но такой пользователь не найден." + +#: mediagoblin/templates/mediagoblin/moderation/user.html:43 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Ðужно подтверждение почтового адреÑа" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:45 +msgid "" +"Someone has registered an account with this username, but it still has\n" +" to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:58 +msgid "Return to Users Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:60 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 +#, python-format +msgid "%(username)s's profile" +msgstr "Профиль Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %(username)s" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:62 +#, python-format +msgid "BANNED until %(expiration_date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:66 +msgid "Banned Indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:72 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "Ðтот пользователь не заполнил Ñвой профайл (пока)." + +#: mediagoblin/templates/mediagoblin/moderation/user.html:83 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "Редактировать профиль" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:90 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "Смотреть коллекции" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:97 +#, python-format +msgid "Active Reports on %(username)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:104 +msgid "Report ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:105 +msgid "Reported Content" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:106 +msgid "Description of Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:114 +#, python-format +msgid "Report #%(report_number)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:121 +msgid "Reported Comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:123 +msgid "Reported Media Entry" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:134 +#, python-format +msgid "No active reports filed on %(username)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:141 +#, python-format +msgid "All reports on %(username)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:146 +#, python-format +msgid "All reports that %(username)s has filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:160 +msgid "Ban User" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:165 +msgid "UnBan User" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:173 +msgid "Privilege" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:174 +msgid "User Has Privilege" +msgstr "ЕÑть у пользователÑ" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:181 +msgid "Yes" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user.html:183 +msgid "No" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Добавление коллекции" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Добавление ваших файлов" @@ -807,11 +1552,6 @@ msgstr "%(collection_title)s Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <a href=\"%(user_url)s\">% msgid "Edit" msgstr "Изменить" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Удалить" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,7 +1563,7 @@ msgstr "Удалить %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Ð’ Ñамом деле иÑключить %(media_title)s из %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "ИÑключить" @@ -866,24 +1606,21 @@ msgstr "Файлы Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <a href=\"%(user_url)s\">%(username) msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "■ПроÑмотр файлов Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Добавить комментарий" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Добавить Ñтот комментарий" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "в" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Предварительный проÑмотр комментариÑ" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Добавлено</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Добавлен" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -893,7 +1630,7 @@ msgstr "Добавление «%(media_title)s» в коллекцию" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" -msgstr "" +msgstr "+" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58 msgid "Add a new collection" @@ -908,85 +1645,82 @@ msgstr "Ð’Ñ‹ можете Ñледить за ÑтатуÑом обработкРmsgid "Your last 10 successful uploads" msgstr "Ваши поÑледние 10 удавшихÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¾Ðº" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 #, python-format -msgid "%(username)s's profile" -msgstr "Профиль Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %(username)s" +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Извините, но такой пользователь не найден." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Ðужно подтверждение почтового адреÑа" +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "ЗдеÑÑŒ вы можете раÑÑказать о Ñебе." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "Смотреть вÑе файлы %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "Ваши файлы поÑвÑÑ‚ÑÑ Ð·Ð´ÐµÑÑŒ, когда вы их добавите." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "Пока что тут файлов нет…" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 msgid "Almost done! Your account still needs to be activated." msgstr "Почти закончили! Теперь надо активировать ваш аккаунт." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "Через пару мгновений на Ð°Ð´Ñ€ÐµÑ Ð²Ð°ÑˆÐµÐ¹ Ñлектронной почты должно прийти Ñообщение Ñ Ð´Ð°Ð»ÑŒÐ½ÐµÐ¹ÑˆÐ¸Ð¼Ð¸ инÑтрукциÑми." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 msgid "In case it doesn't:" msgstr "РеÑли нет, то:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 msgid "Resend verification email" msgstr "Повторно отправить Ñообщение Ð´Ð»Ñ Ð¿Ð¾Ð´Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð°Ð´Ñ€ÐµÑа Ñлектронной почты" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "Ктоâ€Ñ‚о Ñоздал аккаунт Ñ Ñтим именем, но его еще надо активировать." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." msgstr "ЕÑли Ñто были вы, и еÑли вы потерÑли Ñообщение Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð°, то вы можете <a href=\"%(login_url)s\">войти</a> и отправить его повторно." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 -msgid "Here's a spot to tell others about yourself." -msgstr "ЗдеÑÑŒ вы можете раÑÑказать о Ñебе." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 -msgid "Edit profile" -msgstr "Редактировать профиль" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 -msgid "This user hasn't filled in their profile (yet)." -msgstr "Ðтот пользователь не заполнил Ñвой профайл (пока)." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 -msgid "Browse collections" -msgstr "Смотреть коллекции" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 -#, python-format -msgid "View all of %(username)s's media" -msgstr "Смотреть вÑе файлы %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 -msgid "" -"This is where your media will appear, but you don't seem to have added " -"anything yet." -msgstr "Ваши файлы поÑвÑÑ‚ÑÑ Ð·Ð´ÐµÑÑŒ, когда вы их добавите." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 -#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 -#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 -msgid "There doesn't seem to be any media here yet..." -msgstr "Пока что тут файлов нет…" - #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "(иÑключить)" @@ -1035,39 +1769,75 @@ msgstr "более новые" msgid "older" msgstr "более Ñтарые" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Метки" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Ðе удалоÑÑŒ прочитать файл Ñ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸ÐµÐ¼." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Ой!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Произошла ошибка" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Ðеверный запроÑ" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ позволÑетÑÑ" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." -msgstr "" +msgstr "Похоже, по Ñтому адреÑу нет Ñтраницы. Сожалеем!</p><p>Возможно, Ñтраница, которую вы ищете, была удалена или переехала." + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "год" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "меÑÑц" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "неделÑ" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "день" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "чаÑ" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "мин" #: mediagoblin/user_pages/forms.py:23 msgid "Comment" @@ -1075,10 +1845,9 @@ msgstr "Комментировать" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Ð”Ð»Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‚ÐºÐ¸ можете иÑпользовать Ñзык <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a>." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1100,73 +1869,84 @@ msgstr "-- Выберите --" msgid "Include a note" msgstr "Примечание" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "оÑтавил комментарий к вашему файлу" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Сожалеем: возможноÑть ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Ой, ваш комментарий был пуÑÑ‚." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Ваш комментарий размещён!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "ПожалуйÑта, проверьте введённое и попробуйте ещё раз." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Ðеобходимо выбрать или добавить коллекцию" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "«%s» — уже в коллекции «%s»" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "«%s» добавлено в коллекцию «%s»" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Ð’Ñ‹ удалили файл." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "Файл не удалён, так как вы не подтвердили Ñвою уверенноÑть галочкой." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Ð’Ñ‹ на пороге ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° другого пользователÑ. Будьте оÑторожны." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Ð’Ñ‹ иÑключили файл из коллекции." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "Файл не иÑключён из коллекции, так как вы не подтвердили Ñвоё намерение отметкой." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Ð’Ñ‹ на пороге иÑÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° из коллекции другого пользователÑ. Будьте оÑторожны." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Ð’Ñ‹ удалили коллекцию «%s»" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ð½Ðµ удалена, так как вы не подтвердили Ñвоё намерение отметкой." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Ð’Ñ‹ на пороге ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ð¸ другого пользователÑ. Будьте оÑторожны." diff --git a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo Binary files differindex bc92bb13..cf5070f0 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 07932b77..b401851f 100644 --- a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po @@ -3,20 +3,20 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Martin <zatroch.martin@gmail.com>, 2013. -# Martin Zatroch <zatroch.martin@gmail.com>, 2012. -# Morten Juhl-Johansen Zölde-Fejér <morten@writtenandread.net>, 2012. -# Olle Jonsson <olle.jonsson@gmail.com>, 2012. -# Tanja Trudslev <tanja.trudslev@gmail.com>, 2012. -# <zatroch.martin@gmail.com>, 2011-2012. +# martin, 2013 +# martin, 2012-2013 +# Morten Juhl-Johansen Zölde-Fejér <morten@writtenandread.net>, 2012 +# Olle Jonsson <olle.jonsson@gmail.com>, 2012 +# ttrudslev <tanja.trudslev@gmail.com>, 2012 +# martin, 2011-2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Slovak (http://www.transifex.com/projects/p/mediagoblin/language/sk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -24,253 +24,264 @@ msgstr "" "Language: sk\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: mediagoblin/auth/forms.py:28 +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "PrepáÄ, registrácia na danej inÅ¡tancii nie je povolená." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "PrepáÄ, autentifikácia je vypnutá pre túto inÅ¡tanciu." + +#: mediagoblin/auth/tools.py:43 msgid "Invalid User name or email address." msgstr "Nesprávne použÃvateľské meno alebo e-mailová adresa." -#: mediagoblin/auth/forms.py:29 +#: mediagoblin/auth/tools.py:44 msgid "This field does not take email addresses." msgstr "Toto pole neakceptuje e-mailové adresy." -#: mediagoblin/auth/forms.py:30 +#: mediagoblin/auth/tools.py:45 msgid "This field requires an email address." msgstr "Toto pole vyžaduje e-mailovú adresu." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "PoužÃvateľské meno" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Heslo" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Email adresse" - -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "PoužÃvateľské meno alebo e-mailová adresa" - -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "PrepáÄ, registrácia na danej inÅ¡tancii nie je povolená." - -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "PrepáÄ, rovnaké použÃvateľské meno už existuje." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "PrepáÄ, rovnaká e-mailová adresa už bola použitá na vytvorenie úÄtu." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "VerifikaÄný kÄ¾ÃºÄ alebo použÃvateľské ID nie je správne." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Tvoja e-mailová adresa bola overená. Teraz sa môžeÅ¡ prihlásiÅ¥, upravovaÅ¥ profil a vkladaÅ¥ výtvory!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Overovacà kľúÄ, prÃpadne použÃvateľské meno je nesprávne." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Je potrebné prihlásiÅ¥ sa, aby sme vedeli kam máme e-mail zaslaÅ¥!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Už máš overenú e-mailovú adresu!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Opätovne zaslaÅ¥ overovacà e-mail." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "Pokiaľ daná e-mailová adresa (citlivá na veľkosÅ¥ pÃsma!) je registrovaná, e-mail z inÅ¡trukciami pre zmenu tvojho hesla bol zaslaný." - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "Nemožno nájsÅ¥ nikoho z daným použÃvateľským menom." - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "E-mailová správa z inÅ¡trukciami na zmenu tvojho hesla bola zaslaná." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Nebolo možné zaslaÅ¥ e-mail na opätovné zÃskanie zabudnutého hesla, nakoľko tvoje použÃvateľské meno je neaktÃvne, prÃpadne e-mailová adresa nebola úspeÅ¡ne overená." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Už môžeÅ¡ použiÅ¥ nové heslo pri prihlasovanÃ." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titulok" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Popis výtvoru" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "MôžeÅ¡ využiÅ¥\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> pre formátovanie prÃspevku." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Å tÃtky" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Oddeľ Å¡tÃtky pomocou Äiarky." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Unikátna ÄasÅ¥ adresy" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "Unikátna ÄasÅ¥ adresy nesmie byÅ¥ prázdna" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Titulná ÄasÅ¥ adresy daného média. Zmena poľa nepovinná." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Licencia" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Webstránka" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Daná adresa obsahuje chybu" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Staré heslo" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Vlož svoje staré heslo na dôkaz toho, že vlastnÃÅ¡ daný úÄet." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "ZaÅ¡li mi e-mail keÄ ostatnà okomentujú môj výtvor" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Nové heslo" +msgid "Enable insite notifications about events." +msgstr "PovoliÅ¥ notifikácie ohľadom udalostà na stránke." -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "Preferencia licencie" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "Nasledovná licencia bude použitá ako východzia pre vÅ¡etky tvoje výtvory." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "ZaÅ¡li mi e-mail keÄ ostatnà okomentujú môj výtvor" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "Titulok nesmie byÅ¥ prázdny." -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Popis danej kolekcie" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "Titulná ÄasÅ¥ adresy danej kolekcie. Zmena poľa nepovinná." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Staré heslo" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Vlož svoje staré heslo na dôkaz toho, že vlastnÃÅ¡ daný úÄet." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Nové heslo" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Nová e-mailová adresa" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Heslo" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Vlož svoje heslo pre overenie pravosti úÄtu." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Položku s rovnakou unikátnou ÄasÅ¥ou adresy už niekde máš." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "UpravujeÅ¡ výtvory iného použÃvateľa. Pristupuj zodpovedne. " -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "PrÃloha %s pridaná!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "MôžeÅ¡ upravovaÅ¥ iba svoj vlastný profil." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "UpravujeÅ¡ profil iného použÃvateľa. Pristupuj zodpovedne. " -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Zmeny v profile uložené" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Nesprávne heslo" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Nastavenia úÄtu uložené" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "PotrebujeÅ¡ potvrdiÅ¥ odstránenie svojho úÄtu." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Už máš kolekciu nazvanú ako \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "Kolekcia s týmto Å¡tÃtkom už máš." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "UpravujeÅ¡ kolekciu iného použÃvateľa. Pristupuj zodpovedne. " -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Tvoja e-mailová adresa bola verifikovaná." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Nesprávne heslo" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Nemožno pripojiÅ¥ tému... téma nenastavená\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "Žiadny prieÄinok položiek pre túto tému\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "Odstránené; hoci bol pôvodný symbolický odkaz adresára nájdený.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "Nemožno odkazovaÅ¥ na \"%s\": %s existuje a nie je symbolickým odkazom\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "Preskakujem \"%s\"; opakovane nastavené.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "Nájdený starý odkaz pre \"%s\"; odstraňujem.\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -278,15 +289,202 @@ msgid "" "domain." msgstr "CSRF \"cookie\" neprÃtomný. Toto vidÃÅ¡ najskôr ako výsledok blokovania \"cookie\" súborov a pod.<br/>Uisti sa, že máš povolené ukladanie \"cookies\" pre danú doménu." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "PrepáÄ, nepodporujem tento typ súborov =(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "beh unoconv zlyhal, preskúmajte log záznam" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Konvertovanie videa zlyhalo" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "okmentoval tvoj prÃspevok" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "ÚspeÅ¡ný zápis odberu komentárov pre %s!" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "NebudeÅ¡ dostávaÅ¥ notifikácie ohľadom komentárov pre %s." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "NutnosÅ¥ poskytnúť OAuth token." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "Požadovaný token nenájdený." + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "PoužÃvateľské meno" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Email adresse" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Použivateľské meno alebo e-mail" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "ZostaÅ¥ prihlásený" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "PoužÃvateľské meno alebo e-mailová adresa" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Pokiaľ daná e-mailová adresa (citlivá na veľkosÅ¥ pÃsma!) je registrovaná, e-mail z inÅ¡trukciami pre zmenu tvojho hesla bol zaslaný." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "Nemožno nájsÅ¥ nikoho z daným použÃvateľským menom." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "E-mailová správa z inÅ¡trukciami na zmenu tvojho hesla bola zaslaná." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Nebolo možné zaslaÅ¥ e-mail na opätovné zÃskanie zabudnutého hesla, nakoľko tvoje použÃvateľské meno je neaktÃvne, prÃpadne e-mailová adresa nebola úspeÅ¡ne overená." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "PoužÃvateľské ID nie je správne." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Už môžeÅ¡ použiÅ¥ nové heslo pri prihlasovanÃ." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Tvoje heslo bolo úspeÅ¡ne zmenené" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Nastav svoje nové heslo" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Nastav heslo" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "MenÃm heslo použÃvateľa %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "UložiÅ¥" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "EÅ¡te stále nemáš úÄet?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Vytvor si jeden tu!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "ObnoviÅ¥ heslo" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "ZaslaÅ¥ inÅ¡trukcie" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Zabudnuté heslo?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Poloha" @@ -296,6 +494,10 @@ msgstr "Poloha" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "ZobraziÅ¥ na <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "PovoliÅ¥" @@ -350,7 +552,7 @@ msgstr "Presmerovacie URI pre aplikácie, toto pole\nje <strong>požadované</st msgid "This field is required for public clients" msgstr "Dané pole je požadované pre verejných klientov." -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Klient {0} bol registrovaný!" @@ -363,88 +565,357 @@ msgid "Your OAuth clients" msgstr "Tvoji autorizovanà OAuth klienti" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "PridaÅ¥" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "PrepáÄ, úÄet pre dané OpenID už existuje." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "PrepáÄ, OpenID server nebol nájdený" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "Nenájdená žiadna OpenID služba pre %s" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Verifikácia %s zlyhala: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Verifikácia zruÅ¡ená" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "URL k tvojmu OpenID úpeÅ¡ne zaznamenaný." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "NesmieÅ¡ odstániÅ¥ svoj jediný OpenID URL, pokým nemáš nastavené heslo" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "OpenID nie je registrované k tomuto úÄtu." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "OpenID úspeÅ¡ne odstránené." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "PridaÅ¥ OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "OdstrániÅ¥ OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "OdstrániÅ¥" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "PrihlásiÅ¥ sa" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Prihlásenie zlyhalo!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "Prihlás sa pre vytvorenie úÄtu!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "Alebo sa prihlás z heslom!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "Alebo sa prihlás z OpenID!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "Alebo sa registruj z OpenID!" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "PrepáÄ, úÄet na daný Persona e-mail už existuje." + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "E-mailová adresa Persona úspeÅ¡ne odstránená." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "NesmieÅ¡ odstrániÅ¥ svoj jediný Persona e-mail, pokým nie je nastavené heslo." + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "Persona e-mail nie je registrovaný k tomuto úÄtu." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "PrepáÄ, úÄet z danou Persona e-mailovou adresou už existuje." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Tvoj Persona e-mail úspeÅ¡ne uložený." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "OdstrániÅ¥ Persona e-mail" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "PridaÅ¥ Persona e-mail" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "Alebo sa prihlás z Persona!" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "Alebo sa registruj z Persona!" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Nesprávny typ súboru pre dané médium." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "KopÃrovanie na verejný úložný priestor zlyhalo." + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "Prijateľný spracúvavaný súbor nenájdený" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Súbor" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "MusÃÅ¡ poskytnúť súbor." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Skvelé! Pridané!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "Kolekcia \"%s\" pridaná!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Obrázok hysterického goblina" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Over si e-mailovú adresu!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "odhlásiÅ¥ sa" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "PrihlásiÅ¥ sa" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "ÚÄet použÃvateľa <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "ZmeniÅ¥ nastavenia úÄtu" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Sekcia spracovania výtvorov" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "OdhlásiÅ¥ sa" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "PridaÅ¥ výtvor" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "VytvoriÅ¥ novú kolekciu" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Aktuálne výtvory" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Autorizácia" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "AutorizovaÅ¥" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Si prihlásený/á ako" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "ChceÅ¡ sa autorizovaÅ¥" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "v neznámej aplikácii" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "pre prÃstup k svojmu úÄtu?" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Aplikácie z prÃstupom k tvojmu úÄtu môžu:" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "ZaslaÅ¥ nové výtvory ako ty" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "PrezrieÅ¥ vlastné info (napr. profil, výtvory atÄ.)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "ZmeniÅ¥ tvoje údaje" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "Autorizácia dokonÄená" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "Autorizácia kompletná" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Toto kopÃruj a vlož do svojho klienta:" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Opret en konto!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "VytvoriÅ¥" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Ahoj %(username)s,\n\npre aktiváciu tvojho GNU MediaGoblin úÄtu, otvor nasledujúci odkaz vo\nsvojom prehliadaÄi:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." msgstr "Poháňa nás <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, súÄasÅ¥ projektu <a href=\"http://gnu.org/\">GNU</a>." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -452,147 +923,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Uvoľnené pod <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Zdrojový kód</a> plne dostupný." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "Obrázok hysterického goblina" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "PreskúmaÅ¥" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Ahoj, vitaj na tejto MediaGoblin stránke!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 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:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Pre pridanie vlastných výtvorov, komentárov a viac.. sa prihlás zo svojim MediaGoblin úÄtom." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "Har du ikke en endnu? Det er let!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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\">VytvoriÅ¥ úÄet na tejto stránke</a>\n alebo\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">ZaložiÅ¥ MediaGoblin na vlastnom serveri</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Aktuálne výtvory" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Tu môžeÅ¡ sledovaÅ¥ stav médià spracovávaných na danej inÅ¡tancii." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Výtvory sa spracúvajú" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Žiadne výtvory v procese spracovania" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Nasledovné nahratia nepreÅ¡li spracovanÃm:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Žiadne zlyhané položky!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "Posledných 10 úspeÅ¡ných nahratÃ" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Zatiaľ žiadne spracované položky!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Nastav svoje nové heslo" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Nastav heslo" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "ObnoviÅ¥ heslo" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "ZaslaÅ¥ inÅ¡trukcie" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" "\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Ahoj %(username)s,\n\npre zmenu svojho hesla k GNU MediaGoblin úÄtu, otvor nasledujúci odkaz vo svojom prehliadaÄi:\n\n%(verification_url)s\n\nPokiaľ si myslÃÅ¡, že doÅ¡lo k omylu, tak jednoducho ignoruj túto správu a buÄ Å¡Å¥astným goblinom!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Prihlásenie zlyhalo!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "EÅ¡te stále nemáš úÄet?" +" >Create an account at this site</a>\n" +" or" +msgstr "\n >VytvoriÅ¥ úÄet na tejto stránke</a>\n alebo" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Vytvor si jeden tu!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Zabudnuté heslo?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Opret en konto!" - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "VytvoriÅ¥" - -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" "\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" -"\n" -"%(verification_url)s" -msgstr "Ahoj %(username)s,\n\npre aktiváciu tvojho GNU MediaGoblin úÄtu, otvor nasledujúci odkaz vo\nsvojom prehliadaÄi:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">ZaložiÅ¥ MediaGoblin na vlastnom serveri</a>" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -606,13 +976,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Úprava prÃloh pre %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "PrÃlohy" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "PridaÅ¥ prÃlohu" @@ -629,12 +999,18 @@ msgstr "ZruÅ¡iÅ¥" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "UložiÅ¥ zmeny" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Zmena e-mailu použÃvateľa %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -645,7 +1021,7 @@ msgid "Yes, really delete my account" msgstr "Ãno, skutoÄne odstrániÅ¥ môj úÄet" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "OdstráňiÅ¥ permanentne" @@ -662,10 +1038,14 @@ msgstr "Úprava %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "MenÃm nastavenia úÄtu použÃvateľa %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "OdstrániÅ¥ môj úÄet" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "E-mail" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -677,6 +1057,39 @@ msgstr "Úprava %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Úprava profilu, ktorý vlastnà %(username)s " +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "Ahoj,\n\nChceli sme sa uisiÅ¥, že práve ty si %(username)s. Pokiaľ je tak, nasleduj\nprosÃm odkaz nižšie pre verifikáciu svojej novej e-mailovej adresy.\n\n%(verification_url)s\n\nPokiaľ nie si %(username)s alebo nebola zmena e-mailu žiadaná tebou,\npokojne túto správu ignoruj." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Nové komentáre" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "pred %(formatted_time)s " + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "OznaÄiÅ¥ ako preÄÃtané" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -687,8 +1100,8 @@ msgstr "Výtvory oznaÄené ako: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "StiahnuÅ¥" @@ -711,7 +1124,8 @@ msgid "" msgstr "MôžeÅ¡ zÃskaÅ¥ moderný prehliadaÄ, ktorý\n\ttento zvuk hravo prehrá <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Originálny súbor" @@ -719,6 +1133,11 @@ msgstr "Originálny súbor" msgid "WebM file (Vorbis codec)" msgstr "WebM súbor (Vorbis kodek)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "Vytvorené" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -729,70 +1148,267 @@ msgstr "WebM súbor (Vorbis kodek)" msgid "Image for %(media_title)s" msgstr "Obrázok pre %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "Zapnúť rotáciu" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF súbor" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "PerspektÃva" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "ÄŒelo" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "Vrch" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "Strana" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "StiahnuÅ¥ model" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "Súborový formát" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "Výška objektu" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "PrepáÄ, tento video súbor nepôjde prehraÅ¥, \n\tnakoľko tvoj prehliadaÄ nepodporuje HTML5 \n\tvideo." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "MôžeÅ¡ zÃskaÅ¥ moderný prehliadaÄ, ktorý\n\ttento video súbor hravo prehrá na <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "WebM súbor (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "WebM súbor (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Tu môžeÅ¡ sledovaÅ¥ stav médià spracovávaných na danej inÅ¡tancii." + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Výtvory sa spracúvajú" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Žiadne výtvory v procese spracovania" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Nasledovné nahratia nepreÅ¡li spracovanÃm:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Žiadne zlyhané položky!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "Posledných 10 úspeÅ¡ných nahratÃ" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Zatiaľ žiadne spracované položky!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "PridaÅ¥ kolekciu" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Pridaj svoj výtvor" @@ -811,11 +1427,6 @@ msgstr "%(collection_title)s od <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "UpraviÅ¥" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "OdstrániÅ¥" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -827,7 +1438,7 @@ msgstr "SkutoÄne odstrániÅ¥ %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "SkutoÄne odstrániÅ¥ %(media_title)s z %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "OdstrániÅ¥" @@ -870,24 +1481,21 @@ msgstr "Výtvory, ktoré vlastnà <a href=\"%(user_url)s\">%(username)s</a>" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Prehliadanie výtvorov od <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "PridaÅ¥ komentár" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "PridaÅ¥ tento komentár" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "o" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Náhľad komentára" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Pridané</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Pridané" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -912,85 +1520,107 @@ msgstr "Tu môžeÅ¡ sledovaÅ¥ priebeh spracovania výtvorov pre svoju galériu." msgid "Your last 10 successful uploads" msgstr "Tvojich 10 posledných úspeÅ¡ných nahratÃ" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Profil, ktorý vlastnà %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "PrepáÄ, daný použÃvateľ nenájdený." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Nutné overenie e-mailovej adresy" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Takmer hotovo! EÅ¡te je potrebné aktivovaÅ¥ tvoj úÄet." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "E-mail z inÅ¡trukciami ako na to by ti mal doraziÅ¥ každú chvÃľu." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "V prÃpade, že nie:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Opätovne zaslaÅ¥ overovacà e-mail." +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "ÚÄet s týmto použÃvateľským menom je už registrovaný, avÅ¡ak eÅ¡te stále neaktÃvny." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Pokiaľ si to ty, ale už nemáš uloženú kópiu overovacej správy, tak sa môžeÅ¡ <a href=\"%(login_url)s\">prihlásiÅ¥</a> a preposlaÅ¥ si ju." +msgid "%(username)s's profile" +msgstr "Profil, ktorý vlastnà %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Na tomto mieste môžeÅ¡ povedaÅ¥ o sebe ostatným." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "UpraviÅ¥ profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "DotyÄný použÃvateľ (zatiaľ) nevyplnil svoj profil." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "PrehliadaÅ¥ kolekcie" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "ZobraziÅ¥ vÅ¡etky výtvory, ktoré vlastnà %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "VÅ¡etky tvoje výtvory sa objavia práve tu, zatiaľ vÅ¡ak nemáš niÄ pridané." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Pravdepodobne sa tu nenachádzajú žiadne výtvory..." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Nutné overenie e-mailovej adresy" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Takmer hotovo! EÅ¡te je potrebné aktivovaÅ¥ tvoj úÄet." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "E-mail z inÅ¡trukciami ako na to by ti mal doraziÅ¥ každú chvÃľu." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "V prÃpade, že nie:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Opätovne zaslaÅ¥ overovacà e-mail." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "ÚÄet s týmto použÃvateľským menom je už registrovaný, avÅ¡ak eÅ¡te stále neaktÃvny." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Pokiaľ si to ty, ale už nemáš uloženú kópiu overovacej správy, tak sa môžeÅ¡ <a href=\"%(login_url)s\">prihlásiÅ¥</a> a preposlaÅ¥ si ju." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "(odstrániÅ¥)" @@ -1039,50 +1669,85 @@ msgstr "novÅ¡ie" msgid "older" msgstr "starÅ¡ie" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "OznaÄené ako" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Nemožno preÄÃtaÅ¥ súbor obrázka." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Hopla!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Vyskytla sa chyba" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Zlá požiadavka" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "Požiadavka zaslaná na server nie správna, prosÃm opätovne ju skontroluj" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "Nepovolená operácia" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "PrepÃ¡Ä ÄŒloveÄe, toto nesmieÅ¡!</p><p>Práve si chcel vykonaÅ¥ funkciu, na ktorú nemáš oprávnenie. Opäť si sa pokúšal odstrániÅ¥ vÅ¡etky použÃvateľské úÄty?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "Zdá sa, že na tejto adrese sa niÄ nenachádza. PrepáÄ!</p><p>Pokiaľ si si istý, že adresa je správna, možno bola hľadaná stránka presunutá, respektÃve odstránená." +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "rok" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "mesiac" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "týždeň" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "deň" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "hodina" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minúta" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "Komentár" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "MôžeÅ¡ využiÅ¥ <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> pre formátovanie prÃspevku." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "SmieÅ¡ použÃvaÅ¥ <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Makrdown</a> pre formátovanie textu." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1104,73 +1769,84 @@ msgstr "-- VybraÅ¥ --" msgid "Include a note" msgstr "PridaÅ¥ poznámku" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "okmentoval tvoj prÃspevok" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "SmieÅ¡ použiÅ¥\n<a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\nMarkdown</a> pre formátovanie textu." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "PrepáÄ, komentovanie je vypnuté." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Hopla, tvoj komentár bol prázdny." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Tvoj komentár bol pridaný!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "ProsÃm skontroluj svoje položky a skús znova." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "MusÃÅ¡ vybraÅ¥, prÃpadne pridaÅ¥ kolekciu" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" sa už nachádza v kolekcii \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s pridané do kolekcie \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "Výtvor bol tebou odstránený." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "Výtvor nebol odstránený, nakoľko chýbalo tvoje potvrdenie." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Chystáš sa odstrániÅ¥ výtvory niekoho iného. Pristupuj zodpovedne. " -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "Položka bola z kolekcie odstránená." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "Položka nebola odstránená, nakoľko polÃÄko potvrdenia nebolo oznaÄné." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Chystáš sa odstrániÅ¥ položku z kolekcie iného použÃvateľa. Pristupuj zodpovedne. " -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Kolekcia \"%s\" bola úspeÅ¡ne odstránená." -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "Kolekcia nebola odstránená, nakoľko polÃÄko potrvdenia nebolo oznaÄené." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Chystáš sa odstrániÅ¥ kolekciu iného použÃvateľa. Pristupuj zodpovedne. " diff --git a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo Binary files differindex dd3de81b..41edf626 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 98d62d59..6c40d958 100644 --- a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po @@ -3,15 +3,15 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Jure Repinc <jlp@holodeck1.com>, 2011. +# Jure Repinc <jlp@holodeck1.com>, 2011 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Slovenian (http://www.transifex.com/projects/p/mediagoblin/language/sl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,253 +19,264 @@ msgstr "" "Language: sl\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Oprostite, prijava za ta izvod ni omogoÄena." -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "UporabniÅ¡ko ime" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Geslo" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "E-poÅ¡tni naslov" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Oprostite, prijava za ta izvod ni omogoÄena." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Oprostite, uporabnik s tem imenom že obstaja." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "VaÅ¡ e-poÅ¡tni naslov je bil potrjen. Sedaj se lahko prijavite, uredite svoj profil in poÅ¡ljete slike." -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Potrditveni kljuÄ ali uporabniÅ¡ka identifikacija je napaÄna" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Ponovno poÅ¡iljanje potrditvene e-poÅ¡te." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "" - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Naslov" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Oznake" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Oznaka" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "Oznaka ne sme biti prazna" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Biografija" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Spletna stran" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Geslo" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Vnos s to oznako za tega uporabnika že obstaja." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Urejate vsebino drugega uporabnika. Nadaljujte pazljivo." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Urejate uporabniÅ¡ki profil. Nadaljujte pazljivo." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -273,15 +284,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "UporabniÅ¡ko ime" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "E-poÅ¡tni naslov" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Å e nimate raÄuna?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Ustvarite si ga." + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "" @@ -291,6 +489,10 @@ msgstr "" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -345,7 +547,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -358,236 +560,404 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Prijava" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Prijava ni uspela." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Za vrsto vsebine je bila podana napaÄna datoteka." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Datoteka" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Podati morate datoteko." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Juhej! Poslano." -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Prijava" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Podokno obdelovanja vsebine" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Dodaj vsebino" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Vsebina v obdelavi" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "V obdelavi ni nobene vsebine" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Teh vsebin ni bilo moÄ obdelati:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "" +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Ustvarite raÄun." -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "" +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Ustvari" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 #, python-format msgid "" "Hi %(username)s,\n" "\n" -"to change your GNU MediaGoblin password, open the following URL in \n" +"to activate your GNU MediaGoblin account, open the following URL in\n" "your web browser:\n" "\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" +"%(verification_url)s" +msgstr "Pozdravljeni, %(username)s\n\nZa aktivacijo svojega raÄuna GNU MediaGoblin odprite\nnaslednji URL v svojem spletnem brskalniku:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Prijava ni uspela." +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Å e nimate raÄuna?" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Ustvarite si ga." +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Ustvarite raÄun." +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Ustvari" +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Hi %(username)s,\n" "\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" "\n" -"%(verification_url)s" -msgstr "Pozdravljeni, %(username)s\n\nZa aktivacijo svojega raÄuna GNU MediaGoblin odprite\nnaslednji URL v svojem spletnem brskalniku:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -601,13 +971,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -624,12 +994,18 @@ msgstr "PrekliÄi" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Shrani spremembe" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -640,7 +1016,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "" @@ -657,10 +1033,14 @@ msgstr "Urejanje %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -672,6 +1052,39 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "Urejanje profila – %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -682,8 +1095,8 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "" @@ -706,7 +1119,8 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -714,6 +1128,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -724,70 +1143,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Vsebina v obdelavi" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "V obdelavi ni nobene vsebine" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Teh vsebin ni bilo moÄ obdelati:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "" @@ -806,11 +1422,6 @@ msgstr "" msgid "Edit" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -822,7 +1433,7 @@ msgstr "" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -865,23 +1476,20 @@ msgstr "Vsebina uporabnika <a href=\"%(user_url)s\">%(username)s</a>" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -907,85 +1515,107 @@ msgstr "Tu lahko spremljate stanje vsebin, ki so v obdelavi za vaÅ¡o galerijo." msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "Profil – %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Oprostite, tega uporabnika ni bilo moÄ najti." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "Potrebna je potrditev prek e-poÅ¡te" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Skoraj ste zakljuÄili. Svoj raÄun morate le Å¡e aktivirati." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "V kratkem bi morali prejeti e-poÅ¡to z navodili, kako to storiti." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "ÄŒe je ne prejmete:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Ponovno poÅ¡lji potrditveno e-poÅ¡to" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "Nekdo je s tem uporabniÅ¡kim imenom že registriral raÄun, vendar mora biti Å¡e aktiviran." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "ÄŒe ste ta oseba vi, a ste izgubili potrditveno e-poÅ¡to, se lahko <a href=\"%(login_url)s\">prijavite</a> in jo ponovno poÅ¡ljete." +msgid "%(username)s's profile" +msgstr "Profil – %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Na tem mestu lahko drugim poveste nekaj o sebi." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Uredi profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Ta uporabnik Å¡e ni izpolnil svojega profila." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Prikaži vso vsebino uporabnika %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Tu bo prikazana vaÅ¡a vsebina, a trenutno Å¡e niste dodali niÄ." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Videti je, da tu Å¡e ni nobene vsebine ..." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "Potrebna je potrditev prek e-poÅ¡te" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Skoraj ste zakljuÄili. Svoj raÄun morate le Å¡e aktivirati." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "V kratkem bi morali prejeti e-poÅ¡to z navodili, kako to storiti." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "ÄŒe je ne prejmete:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Ponovno poÅ¡lji potrditveno e-poÅ¡to" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "Nekdo je s tem uporabniÅ¡kim imenom že registriral raÄun, vendar mora biti Å¡e aktiviran." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "ÄŒe ste ta oseba vi, a ste izgubili potrditveno e-poÅ¡to, se lahko <a href=\"%(login_url)s\">prijavite</a> in jo ponovno poÅ¡ljete." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1034,49 +1664,84 @@ msgstr "" msgid "older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Opa!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1099,73 +1764,84 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mo Binary files differindex 276f1273..7d76c92c 100644 --- a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po index 5c965623..10fc1cb3 100644 --- a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po @@ -3,14 +3,14 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Besnik Bleta <besnik@programeshqip.org>, 2012. -# FIRST AUTHOR <EMAIL@ADDRESS>, 2012. +# Besnik <besnik@programeshqip.org>, 2012-2013 +# FIRST AUTHOR <EMAIL@ADDRESS>, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: Albanian (http://www.transifex.com/projects/p/mediagoblin/language/sq/)\n" "MIME-Version: 1.0\n" @@ -20,269 +20,467 @@ msgstr "" "Language: sq\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Na ndjeni, regjistrimi në këtë instancë të shërbimit është i çaktivizuar." -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "Na ndjeni, në këtë instancë raportimi është i çaktivizuar" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "Na ndjeni, mirëfilltësimi është i çaktivizuar për këtë instancë." -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Emër përdoruesi" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Fjalëkalim" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Adresë email" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "Emër përdoruesi ose adresë email e pavlefshme." -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "Emër përdoruesi ose email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "Kjo fushë nuk është për adresa email." -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Na njdeni, regjistrimi në këtë instancë të shërbimit është i çaktivizuar." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "Kjo fushë lyp një adresë email." -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "Na ndjeni, ka tashmë një përdorues me këtë emër." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Na ndjeni, ka tashmë një përdorues me këtë adresë email." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "Kyçi i verifikimit ose id-ja e përdoruesit është e pasaktë." + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Adresa juaj email u verifikua. Tani mund të bëni hyrjen, të përpunoni profilin tuaj, dhe të parashtroni figura!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Kyçi i verifikimit ose id-ja e përdoruesit është e pasaktë" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Duhet të jeni i futur, që ta dimë kujt t'ia çojmë email-in!" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Thuajse e keni verifikuar adresën tuaj email!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Ridërgoni email-in tuaj të verifikimit." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "Është dërguar një email me udhëzime se si të ndryshoni fjalëkalimin tuaj." - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Email-i i ricaktimit të fjalëkalimit nuk u dërgua dot, ngaqë emri juaj i përdoruesit nuk është aktivizuar ose adresa email e llogarisë suaj nuk është verifikuar." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "Tani mun të hyni duke përdorur fjalëkalimin tuaj të ri." - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titull" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Përshkrim i kësaj pune" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "Mund të përdorni\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> për formatim." -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Etiketa" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "Ndajini etiketat me presje." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Identifikues" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "Identifikuesi s'mund të jetë i zbrazët" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "Titulli i adresës së kësaj medie. Zakonisht nuk keni nevojë ta ndryshoni këtë." -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "Leje" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Jetëshkrim" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Site Web" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "Kjo adresë përmban gabime" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Fjalëkalimi i vjetër" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "Jepni fjalëkalimin tuaj të vjetër që të provohet se këtë llogari e zotëroni ju." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Dërgomë email kur të tjerët komentojnë te media ime" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "Fjalëkalimi i ri" +msgid "Enable insite notifications about events." +msgstr "Aktivizoni njoftime të brendshme për veprimtari." -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" -msgstr "" +msgstr "Parapëlqime licence" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" +msgstr "Kjo do të jetë licenca juaj parazgjedhje për forma ngarkimesh." -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "Dërgomë email kur të tjerët komentojnë te media ime" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "Titulli s'mund të jetë i zbrazët" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Përshkrim i këtij koleksioni" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "Pjesa titull e adresës së këtij koleksioni. Zakonisht nuk keni pse e ndryshoni këtë." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Fjalëkalimi i vjetër" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "Jepni fjalëkalimin tuaj të vjetër që të provohet se këtë llogari e zotëroni ju." + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Fjalëkalimi i ri" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "Adresë email e re" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Fjalëkalim" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "Jepni fjalëkalimin tuaj që të provohet se jeni i zoti i kësaj llogarie." + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Ka tashmë një zë me atë identifikues për këtë përdorues." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Po përpunoni media të një tjetër përdoruesi. Hapni sytë." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "Shtuat bashkangjitjen %s!" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." -msgstr "" +msgstr "Mund të përpunoni vetëm profilin tuaj." -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Po përpunoni profilin e një përdoruesi. Hapni sytë." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "Ndryshimet e profilit u ruajtën" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Fjalëkalim i gabuar" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "Rregullimet e llogarisë u ruajtën" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." -msgstr "" +msgstr "Lypset të ripohoni fshirjen e llogarisë suaj." -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" -msgstr "Keni tashmë një koleksion të quajtur \"%s\"!" +msgstr "Keni tashmë një koleksion të quajtur \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "Ka tashmë një koleksion me atë identifikues për këtë përdorues." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "Po përpunoni koleksionin e një tjetër përdoruesi. Hapni sytë." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "Adresa juaj email u verifikua." + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Fjalëkalim i gabuar" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Nuk krijohet dot lidhje për te tema... nuk ka temë të caktuar\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "Nuk ka drejtori asetesh për këtë temë\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "Sidoqoftë, u gjet simlidhje e vjetër drejtorie lidhjesh; u hoq.\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "Nuk krijoi dot lidhje për te \"%s\": %s ekziston dhe nuk është një simlidhje\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "Po anashkalohet \"%s\"; e rregulluar tashmë.\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "U gjet lidhje e vjetër për \"%s\"; po hiqet.\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.<br/>Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "Pa cookie CSRF të pranishme. Ka shumë të ngjarë që të jetë punë e një bllokuesi cookie-sh ose të tillë.<br/>Sigurohuni që të lejoni depozitim cookie-sh për këtë përkatësi." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "Na ndjeni, nuk e mbullojmë këtë lloj kartele :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "unoconv nuk po arrin të xhirohet, kontrolloni kartelën e regjistrimeve" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "Ndërkodimi i videos dështoi" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "Hiqini privilegjet" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "Dëbojeni përdoruesin" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "Dërgojini përdoruesit një mesazh" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "Fshije lëndën" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "Përdoruesi do të dëbohet deri më:" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "Pse po e dëboni këtë Përdorues?" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "Çfarë veprimesh do të ndërmerrni që të zgjidhni këtë raportim?" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "Cilat privilegje do të hiqni?" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "Sinjalizim prej" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "komentoi te postimi juaj" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "U pajtua te komentet në %s!" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "Nuk do të merrni njoftime për komente te %s." + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "Duhet dhënë një oauth_token." + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "S'u gjet token kërkese." + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "Na ndjeni, madhësia e kartelës është shumë e madhe." + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "Na ndjeni, ngarkimi i kësaj kartele do t'ju kalonte tej kufirit tuaj për ngarkime." + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "Na ndjeni, keni arritur kufirin tuaj për ngarkimet." + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Emër përdoruesi" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Adresë email" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Emër përdoruesi ose Email" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "Rri i futur" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Emër përdoruesi ose email" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "Nëse ajo adresë email (siç është shkruajtur!) është e regjistruar, është dërguar një email me udhëzime se si të ndryshoni fjalëkalimin tuaj." + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "S'u gjet dot dikush me atë emër përdoruesi." + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Është dërguar një email me udhëzime se si të ndryshoni fjalëkalimin tuaj." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Email-i i ricaktimit të fjalëkalimit nuk u dërgua dot, ngaqë emri juaj i përdoruesit nuk është aktivizuar ose adresa email e llogarisë suaj nuk është verifikuar." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "Id-ja e përdoruesit është e pasaktë." + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Tani mun të hyni duke përdorur fjalëkalimin tuaj të ri." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "Nuk jeni më një përdorues aktiv. Ju lutemi, lidhuni me përgjegjësin e sistemit që të aktivizoni llogarinë tuaj." + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Fjalëkalimi juaj u ndryshua me sukses" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "Caktoni fjalëkalimin tuaj të ri" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "Caktoni fjalëkalim" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "Ndryshim i fjalëkalimit për %(username)s" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Ruaje" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Nuk keni ende një llogari?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Krijoni një këtu!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "Ndryshoni fjalëkalimin tuaj." + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Rimerrni fjalëkalimin" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Dërgo udhëzime" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Harruat fjalëkalimin tuaj?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "Vend" @@ -292,6 +490,10 @@ msgstr "Vend" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "Shiheni te <a href=\"%(osm_url)s\">OpenStreetMap</a>" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "Për të krijuar një llogari, hyni!" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "Lejoje" @@ -346,101 +548,370 @@ msgstr "URI ridrejtimi për zbatimin, kjo fushë\n është <strong>e msgid "This field is required for public clients" msgstr "Kjo fushë është e domosdoshme për klientë publikë" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "Klienti {0} u regjistrua!" #: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 msgid "OAuth client connections" -msgstr "" +msgstr "Lidhje klienti OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "Klientët tuaj OAuth" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "Shtoni" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "Na ndjeni, ka tashmë një llogari të regjistruar për atë OpenID." + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "Na ndjeni, nuk u gjet dot shërbyesi i OpenID-ve" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "Nuk u gjet shërbim OpenID për %s" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "Verifikimi i %s dështoi: %s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "Verifikimi u anulua" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "Url-ja e OpenID-së suaj u ruajt me sukses." + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "Nuk mundeni të fshini URL-në e të vetmes OpenID tuajës, veç në paçi të caktuar një fjalëkalim" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "Kjo OpenID nuk është e regjistruar për këtë llogari." + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "OpenID u hoq me sukses." + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "Shtoni një OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "Fshini një OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Fshije" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Hyni" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Hyrja dështoi!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "Hyni, që të krijoni një llogari!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "Ose bëni hyrjen me një fjalëkalim!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "Ose bëni hyrjen me OpenID!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "Ose regjistrohuni me OpenID!" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "Na ndjeni, ka tashmë një llogari të regjistruar për këtë email Persona-je." + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "Adresa email e Persona-s u hoq me sukses." + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "Nuk mund të fshini adresën tuaj të vetme email Persona-je pa caktuar fjalëkalimin tuaj." + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "Ajo adresë email-i Persona-je nuk është e regjistruar për këtë llogari." + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "Na ndjeni, ka tashmë të regjistruar një llogari me atë adresë email Persona-je." + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "Adresa email e Persona-s suaj u ruajt me sukses." + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "Fshini një adresë email Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "Shtoni një adresë email Persona" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "Ose bëni hyrjen me Persona!" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "Ose regjistrohuni me Persona!" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Kartelë e gabuar e dhënë për llojin e medias." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "Kopjimi te një depozitim publik dështoi." + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "Nuk u gjet një kartelë e pranueshme përpunimi" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "Madhësi maksimum kartele: {0} mb" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Kartelë" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "Për formatim teksti mund të përdorni\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a>." + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Duhet të jepni një kartelë." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Yhaaaaaa! U parashtrua!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "U shtua koleksioni \"%s\"!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "Jeni Dëbuar." + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "Figurë e gungaçi duke bërë shtriqje" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "Jeni dëbuar" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "deri më %(until_when)s" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "pafundësisht" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Verifikoni email-in tuaj!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "dilni" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Hyni" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "Llogaria e <a href=\"%(user_url)s\">%(user_name)s</a>" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "Ndryshoni rregullime llogarie" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" -msgstr "Paneli i Përpunimit të Medias" +msgstr "Paneli i përpunimit të medias" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "Dilni" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Shtoni media" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Krijoni koleksion të ri" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "Paneli i administrimit të përdoruesve" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "Paneli i administrimit të raporteve" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Mediat më të reja" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "Autorizim" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "Autorizo" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "Keni hyrë si" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "Doni të autorizoni" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "një zbatim të panjohur" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr " të hyjë dhe përdorë llogarinë tuaj? " + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "Zbatimet me hyrje në llogarinë tuaj munden të:" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "Postojnë media të re si ju" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "Të shohin të dhëna tuajat (p.sh profilin, media, etj...)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "Të ndryshojnë të dhënat tuaja personale" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "Autorizimi Përfundoi" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "Autorizim i Plotësuar" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "Këtë kopjojeni dhe ngjiteni te klienti juaj:" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Krijoni një llogari!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "Krijoje" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Njatjeta %(username)s,\n\nqë të aktivizoni llogarinë tuaj te GNU MediaGoblin hapeni URL-në vijuese te\nshfletuesi juaj web:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." -msgstr "" +msgstr "Bazuar në <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, një projekt <a href=\"http://gnu.org/\">GNU</a>." -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -448,147 +919,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "Hedhur në qarkullim sipas <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL-së</a>. <a href=\"%(source_link)s\">Kodi burim</a> është i passhëm." -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "Kushtet e Shërbimit" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "Eksploroni" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "Tungjatjeta juaj, mirë se vini te ky site MediaGoblin!" -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 msgid "" "This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " "extraordinarily great piece of media hosting software." msgstr "Ky site përdor <a href=\"http://mediagoblin.org\">MediaGoblin</a>, një program jashtëzakonisht i shkëlqyer për strehim mediash." -#: mediagoblin/templates/mediagoblin/root.html:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "Për të shtuar media tuajën, për të bërë komente, dhe të tjera, mund të hyni përmes llogarisë suaj MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "Nuk keni ende një të tillë? Është e lehtë!" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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\">Krijoni një llogarin te ky site</a>\n ose\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Instaloni dhe rregulloni MediaGoblin-in te shërbyesi juaj</a>" - -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Mediat më të reja" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "Këtu mund të ndiqni gjendjen e medias që po përpunohet në këtë instancë." - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Media në përpunim" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Pa media në përpunim" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "Nuk arritën të kryheshin këto ngarkime:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "Pa zëra të dështuar!" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "10 Ngarkimet e Fundit të Suksesshme" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "Ende pa zëra të përpunuar!" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "Caktoni fjalëkalimin tuaj të ri" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "Caktoni fjalëkalim" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Rimerrni fjalëkalimin" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Dërgo udhëzime" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" "\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Njatjeta %(username)s,\n\nqë të ndryshoni fjalëkalimin tuaj për GNU MediaGoblin, hapeni URL-në vijuese në \nshfletuesin tuaj web:\n\n%(verification_url)s\n\nNëse mendoni se këtu ka gabim, thjesht shpërfilleni këtë email dhe vazhdoni të jeni\nnjë djallush i lumtur!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Hyrja dështoi!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Nuk keni ende një llogari?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Krijoni një këtu!" +" >Create an account at this site</a>\n" +" or" +msgstr "\n >Krijoni një llogari te ky site</a>\n ose" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Harruat fjalëkalimin tuaj?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "Krijoni një llogari!" - -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "Krijoje" - -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" -"\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" "\n" -"%(verification_url)s" -msgstr "Njatjeta %(username)s,\n\nqë të aktivizoni llogarinë tuaj te GNU MediaGoblin hapeni URL-në vijuese te\nshfletuesi juaj web:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Instaloni dhe përgatisni MediaGoblin-in në shërbyesin tuaj</a>" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -602,13 +972,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "Po përpunohen bashkangjitjet për %(media_title)s" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "Bashkangjitje" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "Shtoni bashkangjitje" @@ -625,23 +995,29 @@ msgstr "Anuloje" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Ruaji ndryshimet" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "Ndryshim i email-it për %(username)s" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" -msgstr "" +msgstr "Të fshihet vërtet përdoruesi '%(user_name)s' dhe krejt media/komentet përkatëse?" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 msgid "Yes, really delete my account" -msgstr "" +msgstr "Po, fshijeni vërtet llogarinë time" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "Fshije përgjithmonë" @@ -658,9 +1034,13 @@ msgstr "Po përpunohet %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "Po ndryshohen rregullimet e llogarisë %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" -msgstr "" +msgstr "Fshije llogarinë time" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Email" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format @@ -673,6 +1053,39 @@ msgstr "Po përpunohet %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "Po përpunohet profili i %(username)s" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "Njatjeta,\n\nDonim të verifikonim që jeni %(username)s. Nëse është kështu, atëherë, \nju lutemi, ndiqni lidhjen më poshtë që të verifikohet adresa juaj email e re.\n\n%(verification_url)s\n\nNëse nuk jeni %(username)s ose nuk kërkuat ndryshim email-i, mund\nta shpërfillni këtë email." + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "Komente të reja" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)s më parë" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "Shënoji të tëra si të lexuara" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -683,8 +1096,8 @@ msgstr "Media e etiketuar me:: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "Shkarkojeni" @@ -707,7 +1120,8 @@ msgid "" msgstr "Një shfletues web modern që mund të luajë \n\taudion mund ta merrni te <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "Kartela origjinale" @@ -715,6 +1129,11 @@ msgstr "Kartela origjinale" msgid "WebM file (Vorbis codec)" msgstr "Kartelë WebM (kodek Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "U krijua" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,70 +1144,267 @@ msgstr "Kartelë WebM (kodek Vorbis)" msgid "Image for %(media_title)s" msgstr "Figurë për %(media_title)s" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "Kartelë PDF" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "Perspektivë" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "Ball" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "Krye" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "Anë" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "Shkarkojeni modelin" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "Format Kartele" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "Lartësi Objekti" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." -msgstr "" +msgstr "Na ndjeni, kjo video nuk do të punojë ngaqë\n shfletuesi juaj web nuk mbulon videot\n HTML5." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" -msgstr "" +msgstr "Mund të merrni një shfletues web modern që \n është në gjendje ta shfaqë këtë video, te <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "Kartelë WebM (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "Këtu mund të ndiqni gjendjen e medias që po përpunohet në këtë instancë." -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "Kartelë WebM (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Media në përpunim" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Pa media në përpunim" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "Nuk arritën të kryheshin këto ngarkime:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "Pa zëra të dështuar!" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "10 ngarkimet e fundit të suksesshme" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "Ende pa zëra të përpunuar!" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "Na ndjeni, nuk u gjet raport i tillë." + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "Kthehuni te Paneli i Raportimeve" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "Raport" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "Koment i raportuar" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "\n â– Media e raportuar nga <a href=\"%(user_url)s\">%(user_name)s</a>\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "\n LËNDË NGA\n <a href=\"%(user_url)s\"> %(user_name)s</a>\n ËSHTË FSHIRË\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "Zgjidheni" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "Zgjidheni Këtë Raport" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "Gjendje" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "ZGJIDHUR" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "Nuk mund të ndërmerrni veprim kundër një përgjegjësi" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "Panel raportimesh" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "\n Këtu mund të kërkoni nëpër raportet që janë depozituar nga përdoruesit.\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "Raportime Aktive të Depozituar" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "Shkelës" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "Raportuar Më" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "Raportuar Nga" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "Arsye" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "\n Raport Komenti #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "\n Raportim Media #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "S'u gjetën raportime të hapur." + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "Raportime të Mbyllur" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "Zgjidhur" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "Veprimi i Ndërmarrë" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "\n Raportim i Mbyllur #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "S'u gjetën raportime të mbyllur." + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "Panel përdoruesi" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "\n Këtu mund të kërkoni për përdorues, me qëllim marrjen e masave ndëshkuese për ta.\n " + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "Përdorues Aktivë" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "ID" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "Ardhur Më" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "# i Komenteve të Postuara" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "S'u gjetën përdorues." #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "Shtoni një koleksion" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "Shtoni media tuajën" @@ -807,11 +1423,6 @@ msgstr "%(collection_title)s nga <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "Përpunoni" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "Fshije" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,19 +1434,19 @@ msgstr "Të fshihet vërtet %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "Të hiqet vërtet %(media_title)s nga %(collection_title)s?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "Hiqe" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 #, python-format msgid "%(username)s's collections" -msgstr "" +msgstr "Koleksione të %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" -msgstr "" +msgstr "Koleksione të <a href=\"%(user_url)s\">%(username)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -854,7 +1465,7 @@ msgstr "Media nga %(username)s" msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "Media të <a href=\"%(user_url)s\">%(username)s</a> me etiketën <a href=\"%(tag_url)s\">%(tag)s</a>" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -866,30 +1477,27 @@ msgstr "Media nga <a href=\"%(user_url)s\">%(username)s</a>" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– Po shfletoni media nga <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "Shtoni një koment" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "Shtoje këtë koment" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "te" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "Paraparje Komenti" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>Shtuar më</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "U shtua" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 #, python-format msgid "Add “%(media_title)s†to a collection" -msgstr "" +msgstr "Shtojeni “%(media_title)s†te një koleksion" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" @@ -908,96 +1516,118 @@ msgstr "Gjendjen e medias që po përpunohet për galerinë tuaj mund ta ndiqni msgid "Your last 10 successful uploads" msgstr "10 ngarkimet tuaja më të suksesshme" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "<h2>Depozitoni një Raportim</h2>" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "Po raportohet ky Koment" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "Po raportohet ky Zë Media" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "\n â– Botuar nga <a href=\"%(user_url)s\"\n class=\"comment_authorlink\">%(username)s</a>\n " + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "Raportim Kartele" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format msgid "%(username)s's profile" msgstr "Profili i %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Na ndjeni, nuk u gjet përdorues i tillë." +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "Ja një vend t'i tregoni botës mbi veten." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "Përpunoni profil" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "Ky përdorues nuk e ka plotësuar (ende) profilin e vet." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "Shfletoni koleksionet" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "Shihni krejt mediat nga %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "Media juaj do të shfaqet këtu, por nuk duket të keni shtuar gjë ende." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "Nuk duket ende të ketë ndonjë media këtu..." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 msgid "Email verification needed" msgstr "Lypset verifikimi i email-it" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 msgid "Almost done! Your account still needs to be activated." msgstr "Pothuajse mbaruam! Llogaria juaj ende lyp aktivizimin." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "Brenda pak çastesh duhet t'ju mbërrijë një email me udhëzime se si të krhyet kjo." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 msgid "In case it doesn't:" msgstr "Në rast se jo:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 msgid "Resend verification email" msgstr "Ridërgo email-in e verifikimit" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "Dikush ka regjistruar një llogari me këtë emër përdoruesi, por ajo duhet aktivizuar." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." msgstr "Nëse jeni ju ai person, por keni humbur email-in tuaj të verifikimit, mund të <a href=\"%(login_url)s\">hyni</a> dhe ta ridërgoni." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 -msgid "Here's a spot to tell others about yourself." -msgstr "Ja një vend t'i tregoni botës mbi veten." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 -msgid "Edit profile" -msgstr "Përpunoni profil" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 -msgid "This user hasn't filled in their profile (yet)." -msgstr "Ky përdorues nuk e ka plotësuar (ende) profilin e vet." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 -msgid "Browse collections" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 -#, python-format -msgid "View all of %(username)s's media" -msgstr "Shihni krejt mediat nga %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 -msgid "" -"This is where your media will appear, but you don't seem to have added " -"anything yet." -msgstr "Media juaj do të shfaqet këtu, por nuk duket të keni shtuar gjë ende." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 -#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 -#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 -msgid "There doesn't seem to be any media here yet..." -msgstr "Nuk duket ende të ketë ndonjë media këtu..." - #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "(hiqe)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" -msgstr "" +msgstr "Pjesë e koleksionit" #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "Shtoje te një koleksion" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 @@ -1035,50 +1665,85 @@ msgstr "më të reja" msgid "older" msgstr "më të vjetra" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "Raportoni media" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "Etiketuar me" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Nuk lexoi dot kartelën e figurës." -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Oooh!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "Ndodhi një gabim" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "Kërkesë e Gabuar" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "Kërkesa e dërguar te shërbyesi është e mangët, ju lutemi, rikontrollojeni" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "Veprim i palejuar" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "Më ndjeni or trim, nuk ju lë dot ta bëni këtë!</p><p>Provuat të kryeni një funksion që nuk lejohet. Keni provuar prapë të fshini krejt llogaritë e përdoruesve?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "Nuk duket se ka ndonjë faqe në këtë adresë. Na ndjeni!</p><p>Nëse jeni i sigurt se kjo adresë është e saktë, ndoshta faqja që po kërkoni është lëvizur ose fshirë." +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "vit" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "muaj" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "javë" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "ditë" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "orë" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "minutë" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" -msgstr "" +msgstr "Koment" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "Për formatime mund të përdorni <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a>." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "Mund të përdorni <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">Markdown</a> për formatime." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1090,7 +1755,7 @@ msgstr "Jam i sigurt se dua që të hiqet ky objekt prek koleksioni" #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "Koleksion" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" @@ -1100,73 +1765,84 @@ msgstr "-- Përzgjidhni --" msgid "Include a note" msgstr "Përfshini një shënim" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "komentoi te postimi juaj" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "Mund të përdorni\n <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n Markdown</a> për formatime." + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "Arsye për Raportim" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Na ndjeni, komentimi është i çaktivizuar." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "Hmmm, komenti juaj qe i zbrazët." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "Komenti juaj u postua!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "Ju lutemi, kontrolloni zërat tuaj dhe riprovoni." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "Duhet të përzgjidhni ose shtoni një koleksion" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" gjendet tashmë te koleksioni \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" u shtua te koleksioni \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "E fshitë median." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "Media nuk u fshi ngaqë nuk i vutë shenjë pohimit se jeni i sigurt." -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Ju ndan një hap nga fshirja e medias të një tjetër përdoruesi. Hapni sytë." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "E fshitë objektin prej koleksionit." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "Objekti nuk u fshi ngaqë, nuk pohuat se jeni të sigurt për këtë." -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "Ju ndan një hap nga fshirja e një objekti prej koleksionit të një përdoruesi tjetër. Hapni sytë." -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "E fshitë koleksionin \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "Koleksioni nuk u fshi ngaqë, nuk pohuat se jeni të sigurt për këtë." -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "Ju ndan një hap nga fshirja e koleksionit të një përdoruesi tjetër. Hapni sytë." diff --git a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo Binary files differindex f6918f71..23613532 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 d482151d..890c44ed 100644 --- a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po @@ -6,9 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: Serbian (http://www.transifex.com/projects/p/mediagoblin/language/sr/)\n" "MIME-Version: 1.0\n" @@ -18,253 +18,264 @@ msgstr "" "Language: sr\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" - -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:60 -msgid "Email address" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." msgstr "" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." msgstr "" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "" -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "" - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -272,15 +283,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "" @@ -290,6 +488,10 @@ msgstr "" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -344,7 +546,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -357,215 +559,327 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 -msgid "Invalid file given for media type." +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." msgstr "" -#: mediagoblin/submit/forms.py:26 -msgid "File" +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" msgstr "" -#: mediagoblin/submit/views.py:51 -msgid "You must provide a file." +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" msgstr "" -#: mediagoblin/submit/views.py:97 -msgid "Woohoo! Submitted!" +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/plugins/openid/views.py:106 #, python-format -msgid "Collection \"%s\" added!" +msgid "Verification of %s failed: %s" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 -msgid "Verify your email!" +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 -msgid "log out" +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 #: mediagoblin/templates/mediagoblin/auth/login.html:28 #: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 msgid "Log in" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:79 -#, python-format -msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 -msgid "Change account settings" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 -msgid "Media processing panel" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 -msgid "Add media" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 -#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 -msgid "Create new collection" +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +"You can't delete your only Persona email address unless you have a password " +"set." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "" + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." msgstr "" +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 @@ -573,7 +887,7 @@ msgstr "" msgid "Create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "" @@ -588,6 +902,62 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -600,13 +970,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -623,12 +993,18 @@ msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -639,7 +1015,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "" @@ -656,10 +1032,14 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -671,6 +1051,39 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -681,8 +1094,8 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "" @@ -705,7 +1118,8 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -713,6 +1127,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -723,70 +1142,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "" @@ -805,11 +1421,6 @@ msgstr "" msgid "Edit" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -821,7 +1432,7 @@ msgstr "" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -864,23 +1475,20 @@ msgstr "" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -906,85 +1514,107 @@ msgstr "" msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." +msgid "%(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "" +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1033,49 +1663,84 @@ msgstr "" msgid "older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1098,73 +1763,84 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo Binary files differindex 28ea51f8..99bd7466 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 76bda505..e89849b6 100644 --- a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po @@ -3,14 +3,14 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <simon@ingenmansland.se>, 2011. -# <transifex@wandborg.se>, 2011, 2012. +# ingenman <simon@ingenmansland.se>, 2011 +# joar <transifex@wandborg.se>, 2011, 2012 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: Swedish (http://www.transifex.com/projects/p/mediagoblin/language/sv/)\n" "MIME-Version: 1.0\n" @@ -20,253 +20,264 @@ msgstr "" "Language: sv\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Vi beklagar, registreringen är avtängd pÃ¥ den här instansen." -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "Användarnamn" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "Lösenord" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "E-postadress" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "Vi beklagar, registreringen är avtängd pÃ¥ den här instansen." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "En användare med det användarnamnet finns redan." -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "Det finns redan en användare med den e-postadressen." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "Din e-postadress är verifierad. Du kan nu logga in, redigera din profil och ladda upp filer!" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "Verifieringsnyckeln eller användar-IDt är fel." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "Du mÃ¥ste vara inloggad för att vi ska kunna skicka meddelandet till dig." -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "Du har redan verifierat din e-postadress!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "Skickade ett nytt verifierings-email." -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "Kunde inte skicka e-postÃ¥terställning av lösenord eftersom ditt användarnamn är inaktivt eller kontots e-postadress har inte verifierats." - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "Titel" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "Beskrivning av verket" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "Taggar" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "Sökvägsnamn" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "Sökvägsnamnet kan inte vara tomt" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "Presentation" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "Hemsida" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "Tidigare lösenord" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Tidigare lösenord" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Lösenord" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "Ett inlägg med det sökvägsnamnet existerar redan." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "Var försiktig, du redigerar nÃ¥gon annans inlägg." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "Var försiktig, du redigerar en annan användares profil." -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Fel lösenord" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Fel lösenord" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -274,15 +285,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Användarnamn" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "E-postadress" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "Kunde inte skicka e-postÃ¥terställning av lösenord eftersom ditt användarnamn är inaktivt eller kontots e-postadress har inte verifierats." + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Har du inget konto än?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Skapa ett här!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "Ã…terställ lösenord" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "Skicka instruktioner" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Glömt ditt lösenord?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "" @@ -292,6 +490,10 @@ msgstr "" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -346,7 +548,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -359,223 +561,335 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "Logga in" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "Inloggning misslyckades!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "Ogiltig fil för mediatypen." -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "Fil" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "Du mÃ¥ste ange en fil" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "Tjohoo! Upladdat!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "Verifiera din e-postadress" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "Logga in" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "Mediabehandlingspanel" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "Lägg till media" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." -msgstr "" - -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Utforska" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Hej, välkommen till den här MediaGoblin-sidan!" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "Senast medier" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" -msgstr "Har du inte ett redan?" - -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" -msgstr "Senast medier" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "Media under behandling" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "Ingen media under behandling" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "De här behandlingarna misslyckades:" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "Ã…terställ lösenord" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "Skicka instruktioner" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "Hej %(username)s,\n\nför att ändra ditt GNU MediaGoblin-lösenord, öppna följande länk i\ndin webbläsare:\n\n%(verification_url)s\n\nOm du misstänker att du fÃ¥tt detta epostmeddelanade av misstag, ignorera det och fortsätt vara ett glatt troll!" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "Inloggning misslyckades!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "Har du inget konto än?" +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "Skapa ett här!" +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "Glömt ditt lösenord?" +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "Skapa ett konto!" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "Skapa" @@ -590,6 +904,62 @@ msgid "" "%(verification_url)s" msgstr "Hej %(username)s,\n\nöppna den följande webbadressen i din webbläsare för att aktivera ditt konto pÃ¥ GNU MediaGoblin:\n\n%(verification_url)s" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Utforska" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Hej, välkommen till den här MediaGoblin-sidan!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "Har du inte ett redan?" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +972,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -625,12 +995,18 @@ msgstr "Avbryt" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "Spara ändringar" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -641,7 +1017,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "" @@ -658,10 +1034,14 @@ msgstr "Redigerar %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -673,6 +1053,39 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "Redigerar %(username)ss profil" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -683,8 +1096,8 @@ msgstr "Media taggat med: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "" @@ -707,7 +1120,8 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -715,6 +1129,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -725,70 +1144,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "Media under behandling" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "Ingen media under behandling" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "De här behandlingarna misslyckades:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "" @@ -807,11 +1423,6 @@ msgstr "" msgid "Edit" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -823,7 +1434,7 @@ msgstr "Vill du verkligen radera %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -866,23 +1477,20 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>s media" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -908,85 +1516,107 @@ msgstr "Här kan du se status för mediabehandling av bilder i ditt galleri." msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)ss profil" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "Ledsen, hittar ingen sÃ¥dan användare." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "E-postadressverifiering krävs." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." -msgstr "Nästan klar! Ditt konto behöver bara aktiveras." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "Ett e-postmeddelande med instruktioner kommer att hamna hos dig inom kort." - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "Om det inte skulle göra det:" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" -msgstr "Skicka ett nytt e-postmeddelande" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "NÃ¥gon har redan registrerat ett konto med det här användarnamnet men det har inte aktiverats." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." -msgstr "Om det är du som är den personen och har förlorat ditt e-postmeddelande med detaljer om hur du verifierar ditt konto sÃ¥ kan du <a href=\"%(login_url)s\">logga in</a> och begära ett nytt." +msgid "%(username)s's profile" +msgstr "%(username)ss profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "Här kan du berätta för andra om dig själv." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "Redigera profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "Den här användaren har inte fyllt i sin profilsida ännu." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "Se all media frÃ¥n %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Här kommer din media att dyka upp, du verkar inte ha lagt till nÃ¥gonting ännu." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "Det verkar inte finnas nÃ¥gon media här ännu." +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "E-postadressverifiering krävs." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Nästan klar! Ditt konto behöver bara aktiveras." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Ett e-postmeddelande med instruktioner kommer att hamna hos dig inom kort." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "Om det inte skulle göra det:" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "Skicka ett nytt e-postmeddelande" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "NÃ¥gon har redan registrerat ett konto med det här användarnamnet men det har inte aktiverats." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "Om det är du som är den personen och har förlorat ditt e-postmeddelande med detaljer om hur du verifierar ditt konto sÃ¥ kan du <a href=\"%(login_url)s\">logga in</a> och begära ett nytt." + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1035,49 +1665,84 @@ msgstr "" msgid "older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "Ojoj!" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1100,73 +1765,84 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Du tänker radera en annan användares media. Var försiktig." -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo Binary files differindex 8cef4593..7de66f2d 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 3586ee78..257f53a7 100644 --- a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po @@ -3,15 +3,15 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# వీవెనౠ<veeven@gmail.com>, 2011. +# వీవెనౠవీరపనేని <veeven@gmail.com>, 2011 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Telugu (http://www.transifex.com/projects/p/mediagoblin/language/te/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,253 +19,264 @@ msgstr "" "Language: te\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "వాడà±à°•à°°à°¿ పేరà±" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "సంకేతపదం" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "ఈమెయిలౠచిరà±à°¨à°¾à°®à°¾" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." msgstr "" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "" -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "" - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "శీరà±à°·à°¿à°•" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "సంకేతపదం" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -273,15 +284,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "వాడà±à°•à°°à°¿ పేరà±" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "ఈమెయిలౠచిరà±à°¨à°¾à°®à°¾" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "మీకౠఇంకా ఖాతా లేదా?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "మీ సంకేతపదానà±à°¨à°¿ మరà±à°šà°¿à°ªà±‹à°¯à°¾à°°à°¾?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "" @@ -291,6 +489,10 @@ msgstr "" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -345,7 +547,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -358,223 +560,335 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 -msgid "Invalid file given for media type." +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." msgstr "" -#: mediagoblin/submit/forms.py:26 -msgid "File" +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" msgstr "" -#: mediagoblin/submit/views.py:51 -msgid "You must provide a file." +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" msgstr "" -#: mediagoblin/submit/views.py:97 -msgid "Woohoo! Submitted!" +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/plugins/openid/views.py:106 #, python-format -msgid "Collection \"%s\" added!" +msgid "Verification of %s failed: %s" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 -msgid "Verify your email!" +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 -msgid "log out" +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 #: mediagoblin/templates/mediagoblin/auth/login.html:28 #: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 msgid "Log in" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:79 -#, python-format -msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "à°ªà±à°°à°µà±‡à°¶à°‚ విఫలమయà±à°¯à°¿à°‚ది!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 -msgid "Change account settings" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 -msgid "Media processing panel" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 -msgid "Add media" +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 -#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 -msgid "Create new collection" +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format +#: mediagoblin/plugins/persona/views.py:144 msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +"You can't delete your only Persona email address unless you have a password " +"set." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "" + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." msgstr "" +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "" + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "à°ªà±à°°à°µà±‡à°¶à°‚ విఫలమయà±à°¯à°¿à°‚ది!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "మీకౠఇంకా ఖాతా లేదా?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "మీ సంకేతపదానà±à°¨à°¿ మరà±à°šà°¿à°ªà±‹à°¯à°¾à°°à°¾?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "" @@ -589,6 +903,62 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +971,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -624,12 +994,18 @@ msgstr "à°°à°¦à±à°¦à±à°šà±‡à°¯à°¿" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "మారà±à°ªà±à°²à°¨à± à°à°¦à±à°°à°ªà°°à°šà±" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -640,7 +1016,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "" @@ -657,10 +1033,14 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -672,6 +1052,39 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -682,8 +1095,8 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "" @@ -706,7 +1119,8 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -714,6 +1128,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -724,70 +1143,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "" @@ -806,11 +1422,6 @@ msgstr "" msgid "Edit" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -822,7 +1433,7 @@ msgstr "" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -865,23 +1476,20 @@ msgstr "" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -907,85 +1515,107 @@ msgstr "" msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." +msgid "%(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "" +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1034,49 +1664,84 @@ msgstr "" msgid "older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1099,73 +1764,84 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.mo Binary files differnew file mode 100644 index 00000000..dbbd07c8 --- /dev/null +++ b/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.po new file mode 100644 index 00000000..1e480f30 --- /dev/null +++ b/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.po @@ -0,0 +1,1847 @@ +# Translations template for PROJECT. +# Copyright (C) 2013 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# +# Translators: +# Caner BAÅžARAN <basaran.caner@gmail.com>, 2013 +msgid "" +msgstr "" +"Project-Id-Version: GNU MediaGoblin\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"Language-Team: Turkish (Turkey) (http://www.transifex.com/projects/p/mediagoblin/language/tr_TR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 0.9.6\n" +"Language: tr_TR\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "Üzgünüz, bu durumda kayıt devre dışıdır." + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "" + +#: mediagoblin/auth/tools.py:116 +msgid "Sorry, a user with that name already exists." +msgstr "Maalesef, bu isimde bir kullanıcı mevcut." + +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 +msgid "Sorry, a user with that email address already exists." +msgstr "Üzgünüz, bu e-posta adresine sahip bir kullanıcı zaten var." + +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 +msgid "" +"Your email address has been verified. You may now login, edit your profile, " +"and submit images!" +msgstr "E-posta adresiniz doÄŸrulandı. Åžimdi giriÅŸ yapabilir, profilinizi düzenleyip ve yeni görüntüleri gönderebilirsiniz!" + +#: mediagoblin/auth/views.py:167 +msgid "The verification key or user id is incorrect" +msgstr "DoÄŸrulama anahtarı veya kullanıcı kimliÄŸi yanlış" + +#: mediagoblin/auth/views.py:185 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:193 +msgid "You've already verified your email address!" +msgstr "Zaten e-posta adresinizi doÄŸruladınız!" + +#: mediagoblin/auth/views.py:203 +msgid "Resent your verification email." +msgstr "DoÄŸrulama e-postasını tekrar yolla." + +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 +#: mediagoblin/user_pages/forms.py:45 +msgid "Title" +msgstr "BaÅŸlık" + +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 +msgid "Description of this work" +msgstr "" + +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 +msgid "Tags" +msgstr "Etiketler" + +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 +msgid "Separate tags by commas." +msgstr "Etikerleri virgül ile ayırın." + +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 +msgid "Slug" +msgstr "" + +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 +msgid "The slug can't be empty" +msgstr "" + +#: mediagoblin/edit/forms.py:42 +msgid "" +"The title part of this media's address. You usually don't need to change " +"this." +msgstr "" + +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 +#: mediagoblin/templates/mediagoblin/utils/license.html:20 +msgid "License" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "Bio" +msgstr "" + +#: mediagoblin/edit/forms.py:58 +msgid "Website" +msgstr "Web sitesi" + +#: mediagoblin/edit/forms.py:60 +msgid "This address contains errors" +msgstr "" + +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "Medyama birisi yorum yazdığında bana e-posta at" + +#: mediagoblin/edit/forms.py:67 +msgid "Enable insite notifications about events." +msgstr "" + +#: mediagoblin/edit/forms.py:69 +msgid "License preference" +msgstr "" + +#: mediagoblin/edit/forms.py:75 +msgid "This will be your default license on upload forms." +msgstr "" + +#: mediagoblin/edit/forms.py:88 +msgid "The title can't be empty" +msgstr "" + +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 +#: mediagoblin/user_pages/forms.py:48 +msgid "Description of this collection" +msgstr "" + +#: mediagoblin/edit/forms.py:97 +msgid "" +"The title part of this collection's address. You usually don't need to " +"change this." +msgstr "" + +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "Eski parola" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "Yeni parola" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "Parola" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 +msgid "An entry with that slug already exists for this user." +msgstr "" + +#: mediagoblin/edit/views.py:91 +msgid "You are editing another user's media. Proceed with caution." +msgstr "BaÅŸka bir kullanıcının medyasını düzenlerken dikkatli davranın." + +#: mediagoblin/edit/views.py:161 +#, python-format +msgid "You added the attachment %s!" +msgstr "" + +#: mediagoblin/edit/views.py:188 +msgid "You can only edit your own profile." +msgstr "" + +#: mediagoblin/edit/views.py:194 +msgid "You are editing a user's profile. Proceed with caution." +msgstr "BaÅŸka bir kullanıcının profilini düzenlerken dikkatli davranın." + +#: mediagoblin/edit/views.py:210 +msgid "Profile changes saved" +msgstr "Profil deÄŸiÅŸiklikleri kaydedildi" + +#: mediagoblin/edit/views.py:243 +msgid "Account settings saved" +msgstr "Hesap ayarları kaydedildi" + +#: mediagoblin/edit/views.py:277 +msgid "You need to confirm the deletion of your account." +msgstr "" + +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 +#, python-format +msgid "You already have a collection called \"%s\"!" +msgstr "" + +#: mediagoblin/edit/views.py:317 +msgid "A collection with that slug already exists for this user." +msgstr "" + +#: mediagoblin/edit/views.py:332 +msgid "You are editing another user's collection. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "Yanlış parola" + +#: mediagoblin/gmg_commands/assetlink.py:60 +msgid "Cannot link theme... no theme set\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:73 +msgid "No asset directory for this theme\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:76 +msgid "However, old link directory symlink found; removed.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + +#: mediagoblin/meddleware/csrf.py:134 +msgid "" +"CSRF cookie not present. This is most likely the result of a cookie blocker " +"or somesuch.<br/>Make sure to permit the settings of cookies for this " +"domain." +msgstr "" + +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 +msgid "Sorry, I don't support that file type :(" +msgstr "Üzgünüz, bu tip dosyaları desteklemiyoruz :(" + +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 +msgid "Video transcoding failed" +msgstr "" + +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "Kullanıcı adı" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "E-posta adresi" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "Kullanıcı adı veya E-posta" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "Kullanıcı adı ya da e-posta" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "Parolanızı nasıl deÄŸiÅŸtireceÄŸinizle ilgili adımları anlatan bir e-posta gönderildi." + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "Åžimdi yeni parolanızı giriÅŸ için kullanabilirsiniz." + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "Parolanız baÅŸarılı bir ÅŸekilde deÄŸiÅŸtirildi" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "Kaydet" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "Hala hesabınız yok mu?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "Åžimdi oluÅŸturun!" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "Parolanı mı unuttun?" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 +msgid "Location" +msgstr "" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52 +#, python-format +msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" +msgstr "" + +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:29 +msgid "Allow" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:30 +msgid "Deny" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:34 +msgid "Name" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:35 +msgid "The name of the OAuth client" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:36 +msgid "Description" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:38 +msgid "" +"This will be visible to users allowing your\n" +" application to authenticate as them." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:40 +msgid "Type" +msgstr "Tür" + +#: mediagoblin/plugins/oauth/forms.py:45 +msgid "" +"<strong>Confidential</strong> - The client can\n" +" make requests to the GNU MediaGoblin instance that can not be\n" +" intercepted by the user agent (e.g. server-side client).<br />\n" +" <strong>Public</strong> - The client can't make confidential\n" +" requests to the GNU MediaGoblin instance (e.g. client-side\n" +" JavaScript client)." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:52 +msgid "Redirect URI" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:54 +msgid "" +"The redirect URI for the applications, this field\n" +" is <strong>required</strong> for public clients." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:66 +msgid "This field is required for public clients" +msgstr "" + +#: mediagoblin/plugins/oauth/views.py:55 +msgid "The client {0} has been registered!" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 +msgid "OAuth client connections" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 +msgid "Your OAuth clients" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 +#: mediagoblin/templates/mediagoblin/submit/collection.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 +msgid "Add" +msgstr "Ekle" + +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "Si" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "GiriÅŸ" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "GiriÅŸ baÅŸarısız!" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "Bu medya türü için geçersiz dosya türü." + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "Dosya" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "Bir dosya saÄŸlamanız gerekir." + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "Hoooop! Gönderildi!" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" +msgstr "E-postanızı doÄŸrulayın!" + +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" +msgstr "çıkış" + +#: mediagoblin/templates/mediagoblin/base.html:115 +#, python-format +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" +msgstr "Hesap ayarlarını deÄŸiÅŸtir" + +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" +msgstr "Medya iÅŸlem paneli" + +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" +msgstr "Çıkış" + +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" +msgstr "Medya ekle" + +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "Hesap oluÅŸtur!" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "OluÅŸtur" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "Merhaba %(username)s,\n\nGNU MediaGoblin hesabınızı etkinleÅŸtirmek için, lütfen aÅŸağıdaki\nURL(baÄŸlantı)'yı Web tarayıcınızda açın:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "KeÅŸfet" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/logo.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 +msgid "MediaGoblin logo" +msgstr "MediaGoblin logo" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:23 +#: mediagoblin/templates/mediagoblin/edit/attachments.html:35 +#, python-format +msgid "Editing attachments for %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 +msgid "Attachments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:57 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 +msgid "Add attachment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:61 +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit.html:41 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:46 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:67 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48 +msgid "Cancel" +msgstr "İptal" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:63 +#: mediagoblin/templates/mediagoblin/edit/edit.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 +msgid "Save changes" +msgstr "DeÄŸiÅŸiklikleri kaydet" + +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 +#, python-format +msgid "Really delete user '%(user_name)s' and all related media/comments?" +msgstr "Gerçekten '%(user_name)s' kullanıcısını ve ilgili tüm medya/yorumları silmek istiyor musun?" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 +msgid "Yes, really delete my account" +msgstr "Evet, gerçekten hesabımı silmek istiyorum" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 +msgid "Delete permanently" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit.html:35 +#, python-format +msgid "Editing %(media_title)s" +msgstr "%(media_title)s düzenleme" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40 +#, python-format +msgid "Changing %(username)s's account settings" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 +msgid "Delete my account" +msgstr "Hesabımı sil" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 +#, python-format +msgid "Editing %(collection_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:34 +#, python-format +msgid "Editing %(username)s's profile" +msgstr "%(username)s profilini düzenleme" + +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)s önce" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + +#: mediagoblin/templates/mediagoblin/listings/collection.html:30 +#: mediagoblin/templates/mediagoblin/listings/collection.html:35 +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 +msgid "Download" +msgstr "İndir" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38 +msgid "Original" +msgstr "Özgün" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:44 +msgid "" +"Sorry, this audio will not work because \n" +"\tyour web browser does not support HTML5 \n" +"\taudio." +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:47 +msgid "" +"You can get a modern web browser that \n" +"\tcan play the audio at <a href=\"http://getfirefox.com\">\n" +"\t http://getfirefox.com</a>!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 +msgid "Original file" +msgstr "Özgün dosya" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63 +msgid "WebM file (Vorbis codec)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "OluÅŸturuldu" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:65 +#, python-format +msgid "Image for %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF dosya" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 +msgid "Perspective" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 +msgid "Front" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 +msgid "Top" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +msgid "Side" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 +msgid "WebGL" +msgstr "WebGL" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 +msgid "Download model" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 +msgid "File Format" +msgstr "Dosya Biçimi" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 +msgid "Object Height" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 +msgid "" +"Sorry, this video will not work because\n" +" your web browser does not support HTML5 \n" +" video." +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 +msgid "" +"You can get a modern web browser that \n" +" can play this video at <a href=\"http://getfirefox.com\">\n" +" http://getfirefox.com</a>!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/submit/collection.html:26 +msgid "Add a collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 +msgid "Add your media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30 +#, python-format +msgid "%(collection_title)s (%(username)s's collection)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:39 +#, python-format +msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:79 +msgid "Edit" +msgstr "Düzenle" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 +#, python-format +msgid "Really delete %(title)s?" +msgstr "Gerçekten %(title)s silmek istiyor musun?" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31 +#, python-format +msgid "Really remove %(media_title)s from %(collection_title)s?" +msgstr "Gerçekten %(collection_title)s %(media_title)s kaldırmak istiyor musun?" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 +msgid "Remove" +msgstr "Kaldır" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 +#, python-format +msgid "%(username)s's collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 +#, python-format +msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "%(username)s medyası" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38 +#, python-format +msgid "" +"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " +"href=\"%(tag_url)s\">%(tag)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 +#, python-format +msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" +msgstr "<a href=\"%(user_url)s\">%(username)s</a> medyası" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:38 +#, python-format +msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 +msgid "Add a comment" +msgstr "Bir yorum ekle" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 +msgid "Add this comment" +msgstr "Bu yorumu ekle" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "Eklendi" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 +#, python-format +msgid "Add “%(media_title)s†to a collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 +msgid "+" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58 +msgid "Add a new collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29 +msgid "" +"You can track the state of media being processed for your gallery here." +msgstr "Burada galerinizdeki iÅŸlenmekte olan medyanın durumunu takip edebilirsiniz." + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89 +msgid "Your last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 +#, python-format +msgid "%(username)s's profile" +msgstr "%(username)s profili" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "Profil düzenle" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "%(username)s tüm medyasını göster" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "E-posta doÄŸrulaması gerekli" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "Neredeyse bitti! Hesabınızı etkinleÅŸtirmeniz gerekiyor." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "Bunun nasıl yapılacağı ile ilgili talimatlar, birkaç dakika içinde size e-posta ulaÅŸacak." + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "DoÄŸrulama e-postası tekrar yolla" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "DoÄŸrulama e-postasını kaybettiyseniz, <a href=\"%(login_url)s\">giriÅŸ</a> yapabilir ve yeniden yollayabilirsiniz." + +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 +msgid "(remove)" +msgstr "(kaldır)" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:21 +msgid "Collected in" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:40 +msgid "Add to a collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 +msgid "feed icon" +msgstr "besleme simgesi" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23 +msgid "Atom feed" +msgstr "Atom besleme" + +#: mediagoblin/templates/mediagoblin/utils/license.html:25 +msgid "All rights reserved" +msgstr "Tüm hakları saklıdır" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:39 +msgid "↠Newer" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:45 +msgid "Older →" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:48 +msgid "Go to page:" +msgstr "Sayfaya git:" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33 +msgid "newer" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44 +msgid "older" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/tools/exif.py:83 +msgid "Could not read the image file." +msgstr "" + +#: mediagoblin/tools/response.py:38 +msgid "Oops!" +msgstr "Amaninnn boo!" + +#: mediagoblin/tools/response.py:39 +msgid "An error occured" +msgstr "" + +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 +msgid "Operation not allowed" +msgstr "" + +#: mediagoblin/tools/response.py:64 +msgid "" +"Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " +"function that you are not allowed to. Have you been trying to delete all " +"user accounts again?" +msgstr "" + +#: mediagoblin/tools/response.py:72 +msgid "" +"There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" +" the address is correct, maybe the page you're looking for has been moved or" +" deleted." +msgstr "" + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "yıl" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "ay" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "hafta" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "gün" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "saat" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "dakika" + +#: mediagoblin/user_pages/forms.py:23 +msgid "Comment" +msgstr "" + +#: mediagoblin/user_pages/forms.py:25 +msgid "" +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:31 +msgid "I am sure I want to delete this" +msgstr "Bunu silmek için eminim" + +#: mediagoblin/user_pages/forms.py:35 +msgid "I am sure I want to remove this item from the collection" +msgstr "" + +#: mediagoblin/user_pages/forms.py:39 +msgid "Collection" +msgstr "" + +#: mediagoblin/user_pages/forms.py:40 +msgid "-- Select --" +msgstr "" + +#: mediagoblin/user_pages/forms.py:42 +msgid "Include a note" +msgstr "" + +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "Maalesef, yorum devre dışı." + +#: mediagoblin/user_pages/views.py:183 +msgid "Oops, your comment was empty." +msgstr "Amaninnn boo, yorumunuz boÅŸtu." + +#: mediagoblin/user_pages/views.py:189 +msgid "Your comment has been posted!" +msgstr "Yorumunuz gönderildi!" + +#: mediagoblin/user_pages/views.py:225 +msgid "Please check your entries and try again." +msgstr "" + +#: mediagoblin/user_pages/views.py:265 +msgid "You have to select or add a collection" +msgstr "" + +#: mediagoblin/user_pages/views.py:276 +#, python-format +msgid "\"%s\" already in collection \"%s\"" +msgstr "" + +#: mediagoblin/user_pages/views.py:282 +#, python-format +msgid "\"%s\" added to collection \"%s\"" +msgstr "" + +#: mediagoblin/user_pages/views.py:307 +msgid "You deleted the media." +msgstr "Medyayı sildiniz." + +#: mediagoblin/user_pages/views.py:319 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "Medya silinmedi çünkü emin olduÄŸunuzu onaylamadınız." + +#: mediagoblin/user_pages/views.py:326 +msgid "You are about to delete another user's media. Proceed with caution." +msgstr "BaÅŸka bir kullanıcının medyasını silerken dikkatli davranın." + +#: mediagoblin/user_pages/views.py:399 +msgid "You deleted the item from the collection." +msgstr "" + +#: mediagoblin/user_pages/views.py:403 +msgid "The item was not removed because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:411 +msgid "" +"You are about to delete an item from another user's collection. Proceed with" +" caution." +msgstr "" + +#: mediagoblin/user_pages/views.py:443 +#, python-format +msgid "You deleted the collection \"%s\"" +msgstr "" + +#: mediagoblin/user_pages/views.py:450 +msgid "" +"The collection was not deleted because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:458 +msgid "" +"You are about to delete another user's collection. Proceed with caution." +msgstr "" diff --git a/mediagoblin/i18n/vi/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/vi/LC_MESSAGES/mediagoblin.mo Binary files differnew file mode 100644 index 00000000..4fd46427 --- /dev/null +++ b/mediagoblin/i18n/vi/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/vi/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/vi/LC_MESSAGES/mediagoblin.po new file mode 100644 index 00000000..b0893bca --- /dev/null +++ b/mediagoblin/i18n/vi/LC_MESSAGES/mediagoblin.po @@ -0,0 +1,1846 @@ +# Translations template for PROJECT. +# Copyright (C) 2013 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: GNU MediaGoblin\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"Language-Team: Vietnamese (http://www.transifex.com/projects/p/mediagoblin/language/vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 0.9.6\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "" + +#: mediagoblin/auth/tools.py:116 +msgid "Sorry, a user with that name already exists." +msgstr "" + +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 +msgid "Sorry, a user with that email address already exists." +msgstr "" + +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 +msgid "" +"Your email address has been verified. You may now login, edit your profile, " +"and submit images!" +msgstr "" + +#: mediagoblin/auth/views.py:167 +msgid "The verification key or user id is incorrect" +msgstr "" + +#: mediagoblin/auth/views.py:185 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:193 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:203 +msgid "Resent your verification email." +msgstr "" + +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 +#: mediagoblin/user_pages/forms.py:45 +msgid "Title" +msgstr "" + +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 +msgid "Description of this work" +msgstr "" + +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 +msgid "Tags" +msgstr "" + +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 +msgid "Separate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 +msgid "Slug" +msgstr "" + +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 +msgid "The slug can't be empty" +msgstr "" + +#: mediagoblin/edit/forms.py:42 +msgid "" +"The title part of this media's address. You usually don't need to change " +"this." +msgstr "" + +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 +#: mediagoblin/templates/mediagoblin/utils/license.html:20 +msgid "License" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "Bio" +msgstr "" + +#: mediagoblin/edit/forms.py:58 +msgid "Website" +msgstr "" + +#: mediagoblin/edit/forms.py:60 +msgid "This address contains errors" +msgstr "" + +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "" + +#: mediagoblin/edit/forms.py:67 +msgid "Enable insite notifications about events." +msgstr "" + +#: mediagoblin/edit/forms.py:69 +msgid "License preference" +msgstr "" + +#: mediagoblin/edit/forms.py:75 +msgid "This will be your default license on upload forms." +msgstr "" + +#: mediagoblin/edit/forms.py:88 +msgid "The title can't be empty" +msgstr "" + +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 +#: mediagoblin/user_pages/forms.py:48 +msgid "Description of this collection" +msgstr "" + +#: mediagoblin/edit/forms.py:97 +msgid "" +"The title part of this collection's address. You usually don't need to " +"change this." +msgstr "" + +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 +msgid "An entry with that slug already exists for this user." +msgstr "" + +#: mediagoblin/edit/views.py:91 +msgid "You are editing another user's media. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:161 +#, python-format +msgid "You added the attachment %s!" +msgstr "" + +#: mediagoblin/edit/views.py:188 +msgid "You can only edit your own profile." +msgstr "" + +#: mediagoblin/edit/views.py:194 +msgid "You are editing a user's profile. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:210 +msgid "Profile changes saved" +msgstr "" + +#: mediagoblin/edit/views.py:243 +msgid "Account settings saved" +msgstr "" + +#: mediagoblin/edit/views.py:277 +msgid "You need to confirm the deletion of your account." +msgstr "" + +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 +#, python-format +msgid "You already have a collection called \"%s\"!" +msgstr "" + +#: mediagoblin/edit/views.py:317 +msgid "A collection with that slug already exists for this user." +msgstr "" + +#: mediagoblin/edit/views.py:332 +msgid "You are editing another user's collection. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 +msgid "Cannot link theme... no theme set\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:73 +msgid "No asset directory for this theme\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:76 +msgid "However, old link directory symlink found; removed.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + +#: mediagoblin/meddleware/csrf.py:134 +msgid "" +"CSRF cookie not present. This is most likely the result of a cookie blocker " +"or somesuch.<br/>Make sure to permit the settings of cookies for this " +"domain." +msgstr "" + +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 +msgid "Sorry, I don't support that file type :(" +msgstr "" + +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 +msgid "Video transcoding failed" +msgstr "" + +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 +msgid "Location" +msgstr "" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52 +#, python-format +msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" +msgstr "" + +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:29 +msgid "Allow" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:30 +msgid "Deny" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:34 +msgid "Name" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:35 +msgid "The name of the OAuth client" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:36 +msgid "Description" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:38 +msgid "" +"This will be visible to users allowing your\n" +" application to authenticate as them." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:40 +msgid "Type" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:45 +msgid "" +"<strong>Confidential</strong> - The client can\n" +" make requests to the GNU MediaGoblin instance that can not be\n" +" intercepted by the user agent (e.g. server-side client).<br />\n" +" <strong>Public</strong> - The client can't make confidential\n" +" requests to the GNU MediaGoblin instance (e.g. client-side\n" +" JavaScript client)." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:52 +msgid "Redirect URI" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:54 +msgid "" +"The redirect URI for the applications, this field\n" +" is <strong>required</strong> for public clients." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:66 +msgid "This field is required for public clients" +msgstr "" + +#: mediagoblin/plugins/oauth/views.py:55 +msgid "The client {0} has been registered!" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 +msgid "OAuth client connections" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 +msgid "Your OAuth clients" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 +#: mediagoblin/templates/mediagoblin/submit/collection.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 +msgid "Add" +msgstr "" + +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "" + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "" + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:115 +#, python-format +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/logo.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 +msgid "MediaGoblin logo" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:23 +#: mediagoblin/templates/mediagoblin/edit/attachments.html:35 +#, python-format +msgid "Editing attachments for %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 +msgid "Attachments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:57 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 +msgid "Add attachment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:61 +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit.html:41 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:46 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:67 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48 +msgid "Cancel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:63 +#: mediagoblin/templates/mediagoblin/edit/edit.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 +msgid "Save changes" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 +#, python-format +msgid "Really delete user '%(user_name)s' and all related media/comments?" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 +msgid "Yes, really delete my account" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 +msgid "Delete permanently" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit.html:35 +#, python-format +msgid "Editing %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40 +#, python-format +msgid "Changing %(username)s's account settings" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 +msgid "Delete my account" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 +#, python-format +msgid "Editing %(collection_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:34 +#, python-format +msgid "Editing %(username)s's profile" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + +#: mediagoblin/templates/mediagoblin/listings/collection.html:30 +#: mediagoblin/templates/mediagoblin/listings/collection.html:35 +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 +msgid "Download" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38 +msgid "Original" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:44 +msgid "" +"Sorry, this audio will not work because \n" +"\tyour web browser does not support HTML5 \n" +"\taudio." +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:47 +msgid "" +"You can get a modern web browser that \n" +"\tcan play the audio at <a href=\"http://getfirefox.com\">\n" +"\t http://getfirefox.com</a>!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 +msgid "Original file" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63 +msgid "WebM file (Vorbis codec)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:65 +#, python-format +msgid "Image for %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 +msgid "Perspective" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 +msgid "Front" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 +msgid "Top" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +msgid "Side" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 +msgid "WebGL" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 +msgid "Download model" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 +msgid "File Format" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 +msgid "Object Height" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 +msgid "" +"Sorry, this video will not work because\n" +" your web browser does not support HTML5 \n" +" video." +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 +msgid "" +"You can get a modern web browser that \n" +" can play this video at <a href=\"http://getfirefox.com\">\n" +" http://getfirefox.com</a>!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/submit/collection.html:26 +msgid "Add a collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 +msgid "Add your media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30 +#, python-format +msgid "%(collection_title)s (%(username)s's collection)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:39 +#, python-format +msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:79 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 +#, python-format +msgid "Really delete %(title)s?" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31 +#, python-format +msgid "Really remove %(media_title)s from %(collection_title)s?" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 +msgid "Remove" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 +#, python-format +msgid "%(username)s's collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 +#, python-format +msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38 +#, python-format +msgid "" +"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " +"href=\"%(tag_url)s\">%(tag)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 +#, python-format +msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:38 +#, python-format +msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 +msgid "Add a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 +msgid "Add this comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 +#, python-format +msgid "Add “%(media_title)s†to a collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 +msgid "+" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58 +msgid "Add a new collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29 +msgid "" +"You can track the state of media being processed for your gallery here." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89 +msgid "Your last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 +#, python-format +msgid "%(username)s's profile" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 +msgid "(remove)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:21 +msgid "Collected in" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:40 +msgid "Add to a collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 +msgid "feed icon" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23 +msgid "Atom feed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/license.html:25 +msgid "All rights reserved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:39 +msgid "↠Newer" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:45 +msgid "Older →" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:48 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33 +msgid "newer" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44 +msgid "older" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/tools/exif.py:83 +msgid "Could not read the image file." +msgstr "" + +#: mediagoblin/tools/response.py:38 +msgid "Oops!" +msgstr "" + +#: mediagoblin/tools/response.py:39 +msgid "An error occured" +msgstr "" + +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 +msgid "Operation not allowed" +msgstr "" + +#: mediagoblin/tools/response.py:64 +msgid "" +"Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " +"function that you are not allowed to. Have you been trying to delete all " +"user accounts again?" +msgstr "" + +#: mediagoblin/tools/response.py:72 +msgid "" +"There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" +" the address is correct, maybe the page you're looking for has been moved or" +" deleted." +msgstr "" + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + +#: mediagoblin/user_pages/forms.py:23 +msgid "Comment" +msgstr "" + +#: mediagoblin/user_pages/forms.py:25 +msgid "" +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:31 +msgid "I am sure I want to delete this" +msgstr "" + +#: mediagoblin/user_pages/forms.py:35 +msgid "I am sure I want to remove this item from the collection" +msgstr "" + +#: mediagoblin/user_pages/forms.py:39 +msgid "Collection" +msgstr "" + +#: mediagoblin/user_pages/forms.py:40 +msgid "-- Select --" +msgstr "" + +#: mediagoblin/user_pages/forms.py:42 +msgid "Include a note" +msgstr "" + +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:189 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:225 +msgid "Please check your entries and try again." +msgstr "" + +#: mediagoblin/user_pages/views.py:265 +msgid "You have to select or add a collection" +msgstr "" + +#: mediagoblin/user_pages/views.py:276 +#, python-format +msgid "\"%s\" already in collection \"%s\"" +msgstr "" + +#: mediagoblin/user_pages/views.py:282 +#, python-format +msgid "\"%s\" added to collection \"%s\"" +msgstr "" + +#: mediagoblin/user_pages/views.py:307 +msgid "You deleted the media." +msgstr "" + +#: mediagoblin/user_pages/views.py:319 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:326 +msgid "You are about to delete another user's media. Proceed with caution." +msgstr "" + +#: mediagoblin/user_pages/views.py:399 +msgid "You deleted the item from the collection." +msgstr "" + +#: mediagoblin/user_pages/views.py:403 +msgid "The item was not removed because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:411 +msgid "" +"You are about to delete an item from another user's collection. Proceed with" +" caution." +msgstr "" + +#: mediagoblin/user_pages/views.py:443 +#, python-format +msgid "You deleted the collection \"%s\"" +msgstr "" + +#: mediagoblin/user_pages/views.py:450 +msgid "" +"The collection was not deleted because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:458 +msgid "" +"You are about to delete another user's collection. Proceed with caution." +msgstr "" diff --git a/mediagoblin/i18n/vi_VN/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/vi_VN/LC_MESSAGES/mediagoblin.mo Binary files differnew file mode 100644 index 00000000..df4f0c64 --- /dev/null +++ b/mediagoblin/i18n/vi_VN/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/vi_VN/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/vi_VN/LC_MESSAGES/mediagoblin.po new file mode 100644 index 00000000..fcfc2445 --- /dev/null +++ b/mediagoblin/i18n/vi_VN/LC_MESSAGES/mediagoblin.po @@ -0,0 +1,1846 @@ +# Translations template for PROJECT. +# Copyright (C) 2013 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: GNU MediaGoblin\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"Language-Team: Vietnamese (Viet Nam) (http://www.transifex.com/projects/p/mediagoblin/language/vi_VN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 0.9.6\n" +"Language: vi_VN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "" + +#: mediagoblin/auth/tools.py:116 +msgid "Sorry, a user with that name already exists." +msgstr "" + +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 +msgid "Sorry, a user with that email address already exists." +msgstr "" + +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 +msgid "" +"Your email address has been verified. You may now login, edit your profile, " +"and submit images!" +msgstr "" + +#: mediagoblin/auth/views.py:167 +msgid "The verification key or user id is incorrect" +msgstr "" + +#: mediagoblin/auth/views.py:185 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:193 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:203 +msgid "Resent your verification email." +msgstr "" + +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 +#: mediagoblin/user_pages/forms.py:45 +msgid "Title" +msgstr "" + +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 +msgid "Description of this work" +msgstr "" + +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 +msgid "Tags" +msgstr "" + +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 +msgid "Separate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 +msgid "Slug" +msgstr "" + +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 +msgid "The slug can't be empty" +msgstr "" + +#: mediagoblin/edit/forms.py:42 +msgid "" +"The title part of this media's address. You usually don't need to change " +"this." +msgstr "" + +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 +#: mediagoblin/templates/mediagoblin/utils/license.html:20 +msgid "License" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "Bio" +msgstr "" + +#: mediagoblin/edit/forms.py:58 +msgid "Website" +msgstr "" + +#: mediagoblin/edit/forms.py:60 +msgid "This address contains errors" +msgstr "" + +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "" + +#: mediagoblin/edit/forms.py:67 +msgid "Enable insite notifications about events." +msgstr "" + +#: mediagoblin/edit/forms.py:69 +msgid "License preference" +msgstr "" + +#: mediagoblin/edit/forms.py:75 +msgid "This will be your default license on upload forms." +msgstr "" + +#: mediagoblin/edit/forms.py:88 +msgid "The title can't be empty" +msgstr "" + +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 +#: mediagoblin/user_pages/forms.py:48 +msgid "Description of this collection" +msgstr "" + +#: mediagoblin/edit/forms.py:97 +msgid "" +"The title part of this collection's address. You usually don't need to " +"change this." +msgstr "" + +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 +msgid "An entry with that slug already exists for this user." +msgstr "" + +#: mediagoblin/edit/views.py:91 +msgid "You are editing another user's media. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:161 +#, python-format +msgid "You added the attachment %s!" +msgstr "" + +#: mediagoblin/edit/views.py:188 +msgid "You can only edit your own profile." +msgstr "" + +#: mediagoblin/edit/views.py:194 +msgid "You are editing a user's profile. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:210 +msgid "Profile changes saved" +msgstr "" + +#: mediagoblin/edit/views.py:243 +msgid "Account settings saved" +msgstr "" + +#: mediagoblin/edit/views.py:277 +msgid "You need to confirm the deletion of your account." +msgstr "" + +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 +#, python-format +msgid "You already have a collection called \"%s\"!" +msgstr "" + +#: mediagoblin/edit/views.py:317 +msgid "A collection with that slug already exists for this user." +msgstr "" + +#: mediagoblin/edit/views.py:332 +msgid "You are editing another user's collection. Proceed with caution." +msgstr "" + +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 +msgid "Cannot link theme... no theme set\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:73 +msgid "No asset directory for this theme\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:76 +msgid "However, old link directory symlink found; removed.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + +#: mediagoblin/meddleware/csrf.py:134 +msgid "" +"CSRF cookie not present. This is most likely the result of a cookie blocker " +"or somesuch.<br/>Make sure to permit the settings of cookies for this " +"domain." +msgstr "" + +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 +msgid "Sorry, I don't support that file type :(" +msgstr "" + +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 +msgid "Video transcoding failed" +msgstr "" + +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 +msgid "Location" +msgstr "" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52 +#, python-format +msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" +msgstr "" + +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:29 +msgid "Allow" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:30 +msgid "Deny" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:34 +msgid "Name" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:35 +msgid "The name of the OAuth client" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:36 +msgid "Description" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:38 +msgid "" +"This will be visible to users allowing your\n" +" application to authenticate as them." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:40 +msgid "Type" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:45 +msgid "" +"<strong>Confidential</strong> - The client can\n" +" make requests to the GNU MediaGoblin instance that can not be\n" +" intercepted by the user agent (e.g. server-side client).<br />\n" +" <strong>Public</strong> - The client can't make confidential\n" +" requests to the GNU MediaGoblin instance (e.g. client-side\n" +" JavaScript client)." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:52 +msgid "Redirect URI" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:54 +msgid "" +"The redirect URI for the applications, this field\n" +" is <strong>required</strong> for public clients." +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:66 +msgid "This field is required for public clients" +msgstr "" + +#: mediagoblin/plugins/oauth/views.py:55 +msgid "The client {0} has been registered!" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 +msgid "OAuth client connections" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 +msgid "Your OAuth clients" +msgstr "" + +#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 +#: mediagoblin/templates/mediagoblin/submit/collection.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 +msgid "Add" +msgstr "" + +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "" + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "" + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:115 +#, python-format +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/logo.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 +msgid "MediaGoblin logo" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:23 +#: mediagoblin/templates/mediagoblin/edit/attachments.html:35 +#, python-format +msgid "Editing attachments for %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 +msgid "Attachments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:57 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 +msgid "Add attachment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:61 +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit.html:41 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:46 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:67 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48 +msgid "Cancel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:63 +#: mediagoblin/templates/mediagoblin/edit/edit.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 +msgid "Save changes" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 +#, python-format +msgid "Really delete user '%(user_name)s' and all related media/comments?" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 +msgid "Yes, really delete my account" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 +msgid "Delete permanently" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit.html:35 +#, python-format +msgid "Editing %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40 +#, python-format +msgid "Changing %(username)s's account settings" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 +msgid "Delete my account" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 +#, python-format +msgid "Editing %(collection_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:34 +#, python-format +msgid "Editing %(username)s's profile" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + +#: mediagoblin/templates/mediagoblin/listings/collection.html:30 +#: mediagoblin/templates/mediagoblin/listings/collection.html:35 +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 +msgid "Download" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38 +msgid "Original" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:44 +msgid "" +"Sorry, this audio will not work because \n" +"\tyour web browser does not support HTML5 \n" +"\taudio." +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:47 +msgid "" +"You can get a modern web browser that \n" +"\tcan play the audio at <a href=\"http://getfirefox.com\">\n" +"\t http://getfirefox.com</a>!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 +msgid "Original file" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63 +msgid "WebM file (Vorbis codec)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:65 +#, python-format +msgid "Image for %(media_title)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 +msgid "Perspective" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 +msgid "Front" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 +msgid "Top" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +msgid "Side" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 +msgid "WebGL" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 +msgid "Download model" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 +msgid "File Format" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 +msgid "Object Height" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 +msgid "" +"Sorry, this video will not work because\n" +" your web browser does not support HTML5 \n" +" video." +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 +msgid "" +"You can get a modern web browser that \n" +" can play this video at <a href=\"http://getfirefox.com\">\n" +" http://getfirefox.com</a>!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/submit/collection.html:26 +msgid "Add a collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 +msgid "Add your media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30 +#, python-format +msgid "%(collection_title)s (%(username)s's collection)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:39 +#, python-format +msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:79 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 +#, python-format +msgid "Really delete %(title)s?" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31 +#, python-format +msgid "Really remove %(media_title)s from %(collection_title)s?" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 +msgid "Remove" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 +#, python-format +msgid "%(username)s's collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 +#, python-format +msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38 +#, python-format +msgid "" +"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " +"href=\"%(tag_url)s\">%(tag)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 +#, python-format +msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:38 +#, python-format +msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 +msgid "Add a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 +msgid "Add this comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 +#, python-format +msgid "Add “%(media_title)s†to a collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 +msgid "+" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58 +msgid "Add a new collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29 +msgid "" +"You can track the state of media being processed for your gallery here." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89 +msgid "Your last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 +#, python-format +msgid "%(username)s's profile" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 +msgid "(remove)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:21 +msgid "Collected in" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:40 +msgid "Add to a collection" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 +msgid "feed icon" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23 +msgid "Atom feed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/license.html:25 +msgid "All rights reserved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:39 +msgid "↠Newer" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:45 +msgid "Older →" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:48 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33 +msgid "newer" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44 +msgid "older" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/tools/exif.py:83 +msgid "Could not read the image file." +msgstr "" + +#: mediagoblin/tools/response.py:38 +msgid "Oops!" +msgstr "" + +#: mediagoblin/tools/response.py:39 +msgid "An error occured" +msgstr "" + +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 +msgid "Operation not allowed" +msgstr "" + +#: mediagoblin/tools/response.py:64 +msgid "" +"Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " +"function that you are not allowed to. Have you been trying to delete all " +"user accounts again?" +msgstr "" + +#: mediagoblin/tools/response.py:72 +msgid "" +"There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" +" the address is correct, maybe the page you're looking for has been moved or" +" deleted." +msgstr "" + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + +#: mediagoblin/user_pages/forms.py:23 +msgid "Comment" +msgstr "" + +#: mediagoblin/user_pages/forms.py:25 +msgid "" +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:31 +msgid "I am sure I want to delete this" +msgstr "" + +#: mediagoblin/user_pages/forms.py:35 +msgid "I am sure I want to remove this item from the collection" +msgstr "" + +#: mediagoblin/user_pages/forms.py:39 +msgid "Collection" +msgstr "" + +#: mediagoblin/user_pages/forms.py:40 +msgid "-- Select --" +msgstr "" + +#: mediagoblin/user_pages/forms.py:42 +msgid "Include a note" +msgstr "" + +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:189 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:225 +msgid "Please check your entries and try again." +msgstr "" + +#: mediagoblin/user_pages/views.py:265 +msgid "You have to select or add a collection" +msgstr "" + +#: mediagoblin/user_pages/views.py:276 +#, python-format +msgid "\"%s\" already in collection \"%s\"" +msgstr "" + +#: mediagoblin/user_pages/views.py:282 +#, python-format +msgid "\"%s\" added to collection \"%s\"" +msgstr "" + +#: mediagoblin/user_pages/views.py:307 +msgid "You deleted the media." +msgstr "" + +#: mediagoblin/user_pages/views.py:319 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:326 +msgid "You are about to delete another user's media. Proceed with caution." +msgstr "" + +#: mediagoblin/user_pages/views.py:399 +msgid "You deleted the item from the collection." +msgstr "" + +#: mediagoblin/user_pages/views.py:403 +msgid "The item was not removed because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:411 +msgid "" +"You are about to delete an item from another user's collection. Proceed with" +" caution." +msgstr "" + +#: mediagoblin/user_pages/views.py:443 +#, python-format +msgid "You deleted the collection \"%s\"" +msgstr "" + +#: mediagoblin/user_pages/views.py:450 +msgid "" +"The collection was not deleted because you didn't check that you were sure." +msgstr "" + +#: mediagoblin/user_pages/views.py:458 +msgid "" +"You are about to delete another user's collection. Proceed with caution." +msgstr "" diff --git a/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.mo Binary files differnew file mode 100644 index 00000000..b76272e5 --- /dev/null +++ b/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.po new file mode 100644 index 00000000..812b2c50 --- /dev/null +++ b/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.po @@ -0,0 +1,1851 @@ +# Translations template for PROJECT. +# Copyright (C) 2013 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# +# Translators: +# <chc@citi.sinica.edu.tw>, 2011 +# cwebber <cwebber@dustycloud.org>, 2013 +# m13253 <m13253@hotmail.com>, 2013 +# medicalwei <medicalwei@gmail.com>, 2012 +# m13253 <m13253@hotmail.com>, 2013 +msgid "" +msgstr "" +"Project-Id-Version: GNU MediaGoblin\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/mediagoblin/language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 0.9.6\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "抱æ‰ï¼Œæœ¬ç«™å·²æš‚åœæ³¨å†Œã€‚" + +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "" + +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "" + +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "æ— æ•ˆç”¨æˆ·åæˆ–电å邮件地å€ã€‚" + +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "æ¤å—段ä¸èƒ½å¡«å†™ç”µå邮件地å€ã€‚" + +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "æ¤å—段需填写电å邮件地å€ã€‚" + +#: mediagoblin/auth/tools.py:116 +msgid "Sorry, a user with that name already exists." +msgstr "抱æ‰ï¼Œè¯¥ç”¨æˆ·åå·²å˜åœ¨ã€‚" + +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 +msgid "Sorry, a user with that email address already exists." +msgstr "抱æ‰ï¼Œå·²æœ‰ç”¨æˆ·ç”¨è¯¥ç”µå邮件注册。" + +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 +msgid "" +"Your email address has been verified. You may now login, edit your profile, " +"and submit images!" +msgstr "您的电å邮件地å€å·²è®¤è¯ã€‚您现在å¯ä»¥ç™»å½•ã€ä¿®æ”¹ä¸ªäººèµ„æ–™å¹¶ä¸Šä¼ å›¾ç‰‡äº†ï¼" + +#: mediagoblin/auth/views.py:167 +msgid "The verification key or user id is incorrect" +msgstr "验è¯ç 错误或用户 ID 错误" + +#: mediagoblin/auth/views.py:185 +msgid "You must be logged in so we know who to send the email to!" +msgstr "您必须登录以便让我们知é“将电å邮件å‘ç»™è°" + +#: mediagoblin/auth/views.py:193 +msgid "You've already verified your email address!" +msgstr "您已ç»è®¤è¯è¿‡ç”µå邮件地å€äº†ï¼" + +#: mediagoblin/auth/views.py:203 +msgid "Resent your verification email." +msgstr "é‡å‘认è¯é‚®ä»¶ã€‚" + +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 +#: mediagoblin/user_pages/forms.py:45 +msgid "Title" +msgstr "æ ‡é¢˜" + +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 +msgid "Description of this work" +msgstr "该作å“çš„æè¿°" + +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "您å¯ä»¥ç”¨ <a href=\"http://wowubuntu.com/markdown/\">Markdown</a> æ¥æŽ’ç‰ˆã€‚" + +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 +msgid "Tags" +msgstr "æ ‡ç¾" + +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 +msgid "Separate tags by commas." +msgstr "用逗å·åˆ†é𔿠‡ç¾ã€‚" + +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 +msgid "Slug" +msgstr "简称" + +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 +msgid "The slug can't be empty" +msgstr "简称ä¸èƒ½ä¸ºç©º" + +#: mediagoblin/edit/forms.py:42 +msgid "" +"The title part of this media's address. You usually don't need to change " +"this." +msgstr "该媒体网å€çš„æ ‡é¢˜éƒ¨ä»½ã€‚通常ä¸éœ€è¦ä¿®æ”¹ã€‚" + +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 +#: mediagoblin/templates/mediagoblin/utils/license.html:20 +msgid "License" +msgstr "许å¯è¯" + +#: mediagoblin/edit/forms.py:52 +msgid "Bio" +msgstr "个性ç¾å" + +#: mediagoblin/edit/forms.py:58 +msgid "Website" +msgstr "网站" + +#: mediagoblin/edit/forms.py:60 +msgid "This address contains errors" +msgstr "本网å€å‡ºé”™äº†" + +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "当有人对我的媒体评论时给我电å邮件" + +#: mediagoblin/edit/forms.py:67 +msgid "Enable insite notifications about events." +msgstr "" + +#: mediagoblin/edit/forms.py:69 +msgid "License preference" +msgstr "许å¯è¯å好" + +#: mediagoblin/edit/forms.py:75 +msgid "This will be your default license on upload forms." +msgstr "è¿™å°†æ˜¯æ‚¨ä¸Šä¼ ç•Œé¢çš„默认许å¯è¯ã€‚" + +#: mediagoblin/edit/forms.py:88 +msgid "The title can't be empty" +msgstr "æ ‡é¢˜ä¸èƒ½æ˜¯ç©ºçš„" + +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 +#: mediagoblin/user_pages/forms.py:48 +msgid "Description of this collection" +msgstr "这个åˆé›†çš„æè¿°" + +#: mediagoblin/edit/forms.py:97 +msgid "" +"The title part of this collection's address. You usually don't need to " +"change this." +msgstr "æ¤åˆé›†ç½‘å€çš„æ ‡é¢˜éƒ¨ä»½ï¼Œé€šå¸¸ä¸éœ€è¦ä¿®æ”¹ã€‚" + +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "旧的密ç " + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "è¾“å…¥æ‚¨çš„æ—§å¯†ç æ¥è¯æ˜Žæ‚¨æ‹¥æœ‰è¿™ä¸ªè´¦æˆ·ã€‚" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "新密ç " + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "密ç " + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 +msgid "An entry with that slug already exists for this user." +msgstr "这个简称已ç»è¢«åˆ«äººç”¨äº†" + +#: mediagoblin/edit/views.py:91 +msgid "You are editing another user's media. Proceed with caution." +msgstr "您æ£åœ¨ä¿®æ”¹åˆ«äººçš„媒体,请å°å¿ƒæ“作。" + +#: mediagoblin/edit/views.py:161 +#, python-format +msgid "You added the attachment %s!" +msgstr "æ‚¨åŠ ä¸Šäº†é™„ä»¶â€œ%sâ€ï¼" + +#: mediagoblin/edit/views.py:188 +msgid "You can only edit your own profile." +msgstr "您åªèƒ½ä¿®æ”¹è‡ªå·±çš„个人资料" + +#: mediagoblin/edit/views.py:194 +msgid "You are editing a user's profile. Proceed with caution." +msgstr "您æ£åœ¨ä¿®æ”¹åˆ«äººçš„个人资料,请å°å¿ƒæ“作。" + +#: mediagoblin/edit/views.py:210 +msgid "Profile changes saved" +msgstr "个人资料已修改" + +#: mediagoblin/edit/views.py:243 +msgid "Account settings saved" +msgstr "账户设置已ä¿å˜" + +#: mediagoblin/edit/views.py:277 +msgid "You need to confirm the deletion of your account." +msgstr "您需è¦ç¡®è®¤åˆ 除您的账户。" + +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 +#, python-format +msgid "You already have a collection called \"%s\"!" +msgstr "æ‚¨å·²ç»æœ‰ä¸€ä¸ªç§°åšâ€œ%sâ€çš„åˆé›†äº†ï¼" + +#: mediagoblin/edit/views.py:317 +msgid "A collection with that slug already exists for this user." +msgstr "è¯¥ç”¨æˆ·å·²ç»æœ‰ä½¿ç”¨è¯¥ç®€ç§°çš„åˆé›†äº†ã€‚" + +#: mediagoblin/edit/views.py:332 +msgid "You are editing another user's collection. Proceed with caution." +msgstr "您æ£åœ¨ä¿®æ”¹åˆ«äººçš„åˆé›†ï¼Œè¯·å°å¿ƒæ“作。" + +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "密ç 错误" + +#: mediagoblin/gmg_commands/assetlink.py:60 +msgid "Cannot link theme... no theme set\n" +msgstr "æ— æ³•é“¾æŽ¥åˆ°ä¸»é¢˜â€¦â€¦æœªè®¾ç½®ä¸»é¢˜\n" + +#: mediagoblin/gmg_commands/assetlink.py:73 +msgid "No asset directory for this theme\n" +msgstr "æ¤ä¸»é¢˜æ²¡æœ‰ç´ æç›®å½•\n" + +#: mediagoblin/gmg_commands/assetlink.py:76 +msgid "However, old link directory symlink found; removed.\n" +msgstr "ä½†æ˜¯æ—§çš„ç›®å½•é“¾æŽ¥å·²ç»æ‰¾åˆ°å¹¶ç§»é™¤ã€‚\n" + +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "æ— æ³•é“¾æŽ¥åˆ°â€œ%sâ€ï¼šâ€œ%sâ€å·²å˜åœ¨ä¸”䏿˜¯é“¾æŽ¥\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "跳过“%sâ€ï¼›å·²è®¾ç½®è¿‡äº†ã€‚\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "“%sâ€çš„æ—§é“¾æŽ¥å·²ç»æ‰¾åˆ°å¹¶ç§»é™¤ã€‚\n" + +#: mediagoblin/meddleware/csrf.py:134 +msgid "" +"CSRF cookie not present. This is most likely the result of a cookie blocker " +"or somesuch.<br/>Make sure to permit the settings of cookies for this " +"domain." +msgstr "CSRF cookie ä¸å˜åœ¨ã€‚很å¯èƒ½æ˜¯ç”±ç±»ä¼¼ cookie å±è”½å™¨é€ æˆçš„。<br />请å…许本域åçš„ cookie 设定。" + +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 +msgid "Sorry, I don't support that file type :(" +msgstr "抱æ‰ï¼Œæˆ‘䏿”¯æŒè¿™æ ·çš„æ–‡ä»¶æ ¼å¼ :(" + +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "æ— æ³•è¿è¡Œ unoconv,请检查日志" + +#: mediagoblin/media_types/video/processing.py:44 +msgid "Video transcoding failed" +msgstr "视频转ç 失败" + +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "åœ¨æ‚¨çš„å†…å®¹å¼ è´´è¯„è®º" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "用户å" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "电å邮件地å€" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "ç”¨æˆ·åæˆ–电å邮件" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "ç”¨æˆ·åæˆ–电å邮件" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "若该邮件地å€ï¼ˆåŒºåˆ†å¤§å°å†™ï¼‰å·²è¢«æ³¨å†Œï¼Œåˆ™å¯†ç 修改说明已通过电å邮件é€è¾¾ã€‚" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "找ä¸åˆ°æœ‰è¯¥ç”¨æˆ·å的人。" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "密ç 修改说明已通过电å邮件é€è¾¾ã€‚" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "æ— æ³•å‘é€å¯†ç æ‰¾å›žé‚®ä»¶ï¼Œå› ä¸ºæ‚¨çš„ç”¨æˆ·åæœªæ¿€æ´»æˆ–者您账户的电åé‚®ä»¶åœ°å€æœªè®¤è¯ã€‚" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "您现在å¯ä»¥ç”¨æ–°çš„å¯†ç æ¥ç™»å½•了ï¼" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "您的密ç å·²æˆåŠŸä¿®æ”¹" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "设置您的新密ç " + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "设置新密ç " + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "修改 %(username)s 的密ç " + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "ä¿å˜" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "还没有账户å—?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "在这里建立一个å§ï¼" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "找回密ç " + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "å‘逿‰¾å›žå¯†ç 说明" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "忘了密ç å—?" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 +msgid "Location" +msgstr "ä½ç½®" + +#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52 +#, python-format +msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" +msgstr "在 <a href=\"%(osm_url)s\">OpenStreetMap</a> 上观看" + +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + +#: mediagoblin/plugins/oauth/forms.py:29 +msgid "Allow" +msgstr "å…许" + +#: mediagoblin/plugins/oauth/forms.py:30 +msgid "Deny" +msgstr "æ‹’ç»" + +#: mediagoblin/plugins/oauth/forms.py:34 +msgid "Name" +msgstr "åç§°" + +#: mediagoblin/plugins/oauth/forms.py:35 +msgid "The name of the OAuth client" +msgstr "OAuth client çš„åç§°" + +#: mediagoblin/plugins/oauth/forms.py:36 +msgid "Description" +msgstr "æè¿°" + +#: mediagoblin/plugins/oauth/forms.py:38 +msgid "" +"This will be visible to users allowing your\n" +" application to authenticate as them." +msgstr "本æè¿°å°†ä¼šè¢«è¿›è¡Œåº”用程åºè®¤è¯çš„用户看到。" + +#: mediagoblin/plugins/oauth/forms.py:40 +msgid "Type" +msgstr "类型" + +#: mediagoblin/plugins/oauth/forms.py:45 +msgid "" +"<strong>Confidential</strong> - The client can\n" +" make requests to the GNU MediaGoblin instance that can not be\n" +" intercepted by the user agent (e.g. server-side client).<br />\n" +" <strong>Public</strong> - The client can't make confidential\n" +" requests to the GNU MediaGoblin instance (e.g. client-side\n" +" JavaScript client)." +msgstr "<strong>秘密</strong> — OAuth client å¯ä»¥å¯¹ GNU MediaGoblin 站点å‘é€ä¸è¢«ç”¨æˆ·ä»£ç†æ‹¦æˆªçš„请求(例如æœåŠ¡ç«¯ä¸Šçš„ client)。\n<strong>公开</strong> — OAuth client æ— æ³•å¯¹ GNU MediaGoblin 站点å‘é€ç§˜å¯†çš„请求(例如客户端的 JavaScript client)。" + +#: mediagoblin/plugins/oauth/forms.py:52 +msgid "Redirect URI" +msgstr "é‡å®šå‘ URI" + +#: mediagoblin/plugins/oauth/forms.py:54 +msgid "" +"The redirect URI for the applications, this field\n" +" is <strong>required</strong> for public clients." +msgstr "æ¤åº”用程åºçš„é‡å®šå‘ URIï¼Œæœ¬å—æ®µåœ¨å…¬å¼€ç±»åž‹çš„ OAuth client 为<strong>å¿…å¡«</strong>。" + +#: mediagoblin/plugins/oauth/forms.py:66 +msgid "This field is required for public clients" +msgstr "æœ¬å—æ®µåœ¨å…¬å¼€ç±»åž‹çš„ OAuth client 为必填" + +#: mediagoblin/plugins/oauth/views.py:55 +msgid "The client {0} has been registered!" +msgstr "OAuth client {0} 注册完æˆï¼" + +#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 +msgid "OAuth client connections" +msgstr "OAuth client 连接" + +#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 +msgid "Your OAuth clients" +msgstr "您的 OAuth client" + +#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 +#: mediagoblin/templates/mediagoblin/submit/collection.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 +msgid "Add" +msgstr "å¢žåŠ " + +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "åˆ é™¤" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "登录" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "登录失败ï¼" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "æä¾›æ–‡ä»¶çš„媒体类型错误。" + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "文件" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." +msgstr "您必须æä¾›ä¸€ä¸ªæ–‡ä»¶" + +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "啊哈ï¼å·²æäº¤ï¼" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "åˆé›†â€œ%sâ€å·²æ–°å¢žï¼" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "满脸问å·çš„哥布林" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" +msgstr "确认您的电å邮件ï¼" + +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" +msgstr "登出" + +#: mediagoblin/templates/mediagoblin/base.html:115 +#, python-format +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +msgstr "<a href=\"%(user_url)s\">%(user_name)s</a> 的账户" + +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" +msgstr "更改账户设置" + +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" +msgstr "媒体处ç†é¢æ¿" + +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" +msgstr "登出" + +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" +msgstr "新增媒体" + +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" +msgstr "新增åˆé›†" + +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "最新的媒体" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "建立一个账户ï¼" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "建立" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "%(username)s 您好:\n\nè¦å¯åЍ GNU MediaGoblin 账户,请在您的æµè§ˆå™¨ä¸æ‰“开下é¢çš„网å€:\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "Powered by <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>,一个 <a href=\"http://gnu.org/\">GNU</a> 项目。" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "以 <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a> 授æƒå‘布。备有<a href=\"%(source_link)s\">æºä»£ç </a>。" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "探索" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "å˜¿ï¼æ¬¢è¿Žæ¥åˆ° MediaGoblin ç«™ï¼ " + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +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/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "您å¯ä»¥ç™»å½•您的 MediaGoblin è´¦æˆ·ä»¥ä¸Šä¼ åª’ä½“ã€å¼ 贴评论ç‰ç‰ã€‚" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "没有账户å—?开账户很简å•ï¼" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/logo.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 +msgid "MediaGoblin logo" +msgstr "MediaGoblin æ ‡å¿—" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:23 +#: mediagoblin/templates/mediagoblin/edit/attachments.html:35 +#, python-format +msgid "Editing attachments for %(media_title)s" +msgstr "编辑 %(media_title)s 的附件" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 +msgid "Attachments" +msgstr "附件" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:57 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 +msgid "Add attachment" +msgstr "新增附件" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:61 +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit.html:41 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:46 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:67 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48 +msgid "Cancel" +msgstr "å–æ¶ˆ" + +#: mediagoblin/templates/mediagoblin/edit/attachments.html:63 +#: mediagoblin/templates/mediagoblin/edit/edit.html:42 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 +msgid "Save changes" +msgstr "ä¿å˜æ›´æ”¹" + +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 +#, python-format +msgid "Really delete user '%(user_name)s' and all related media/comments?" +msgstr "真的è¦åˆ 除用户 %(user_name)s åŠæ‰€æœ‰ç›¸å…³åª’体和评论å—?" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 +msgid "Yes, really delete my account" +msgstr "æ˜¯çš„ï¼ŒçœŸçš„åˆ é™¤æˆ‘çš„è´¦æˆ·" + +#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 +msgid "Delete permanently" +msgstr "æ°¸ä¹…åˆ é™¤" + +#: mediagoblin/templates/mediagoblin/edit/edit.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit.html:35 +#, python-format +msgid "Editing %(media_title)s" +msgstr "编辑 %(media_title)s" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40 +#, python-format +msgid "Changing %(username)s's account settings" +msgstr "æ£åœ¨æ”¹å˜ %(username)s 的账户设置" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 +msgid "Delete my account" +msgstr "åˆ é™¤æˆ‘çš„å¸æˆ·" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 +#, python-format +msgid "Editing %(collection_title)s" +msgstr "编辑 %(collection_title)s" + +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23 +#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:34 +#, python-format +msgid "Editing %(username)s's profile" +msgstr "编辑 %(username)s 的个人资料" + +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)så‰" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + +#: mediagoblin/templates/mediagoblin/listings/collection.html:30 +#: mediagoblin/templates/mediagoblin/listings/collection.html:35 +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "æ¤åª’ä½“è¢«æ ‡è®°ä¸ºï¼š%(tag_name)s" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 +msgid "Download" +msgstr "下载" + +#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38 +msgid "Original" +msgstr "æºæ–‡ä»¶" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:44 +msgid "" +"Sorry, this audio will not work because \n" +"\tyour web browser does not support HTML5 \n" +"\taudio." +msgstr "抱æ‰ï¼Œæ¤å£°éŸ³æ— æ³•æ’æ”¾ï¼Œå› 为您的æµè§ˆå™¨ä¸æ”¯æŒ HTML5 音频。" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:47 +msgid "" +"You can get a modern web browser that \n" +"\tcan play the audio at <a href=\"http://getfirefox.com\">\n" +"\t http://getfirefox.com</a>!" +msgstr "您å¯ä»¥åœ¨ <a href=\"http://getfirefox.com\">http://getfirefox.com</a> å–å¾—å¯ä»¥æ’放æ¤å£°éŸ³çš„æµè§ˆå™¨ï¼" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 +msgid "Original file" +msgstr "æºæ–‡ä»¶" + +#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63 +msgid "WebM file (Vorbis codec)" +msgstr "WebM 文件(Vorbis ç¼–ç )" + +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "已创建" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:65 +#, python-format +msgid "Image for %(media_title)s" +msgstr "%(media_title)s 的照片" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF 文件" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 +msgid "Perspective" +msgstr "é€è§†" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 +msgid "Front" +msgstr "æ£é¢" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 +msgid "Top" +msgstr "é¡¶é¢" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +msgid "Side" +msgstr "ä¾§é¢" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 +msgid "WebGL" +msgstr "WebGL" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 +msgid "Download model" +msgstr "下载模型" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 +msgid "File Format" +msgstr "æ–‡ä»¶æ ¼å¼" + +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 +msgid "Object Height" +msgstr "物体高度" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 +msgid "" +"Sorry, this video will not work because\n" +" your web browser does not support HTML5 \n" +" video." +msgstr "抱æ‰ï¼Œæ¤è§†é¢‘æ— æ³•æ’æ”¾ï¼Œå› 为您的æµè§ˆå™¨ä¸æ”¯æŒ HTML5 视频。" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 +msgid "" +"You can get a modern web browser that \n" +" can play this video at <a href=\"http://getfirefox.com\">\n" +" http://getfirefox.com</a>!" +msgstr "您å¯ä»¥åœ¨ <a href=\"http://getfirefox.com\">http://getfirefox.com</a> å–å¾—å¯ä»¥æ’放æ¤è§†é¢‘çš„æµè§ˆå™¨ï¼" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "æ¤å¤„您å¯ä»¥è¿½è¸ªæœ¬ç«™ç‚¹å¤„ç†åª’体的状æ€ã€‚" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "媒体处ç†ä¸" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "没有æ£åœ¨å¤„ç†ä¸çš„媒体" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "æ— æ³•å¤„ç†è¿™äº›ä¸Šä¼ 内容:" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "没有失败的纪录ï¼" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "最近 10 次æˆåŠŸä¸Šä¼ çš„çºªå½•" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "现在还没有处ç†çš„纪录ï¼" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/submit/collection.html:26 +msgid "Add a collection" +msgstr "新增åˆé›†" + +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 +msgid "Add your media" +msgstr "åŠ å…¥æ‚¨çš„åª’ä½“" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30 +#, python-format +msgid "%(collection_title)s (%(username)s's collection)" +msgstr "%(collection_title)s (%(username)s çš„åˆé›†)" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:39 +#, python-format +msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" + +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:79 +msgid "Edit" +msgstr "编辑" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 +#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 +#, python-format +msgid "Really delete %(title)s?" +msgstr "真的è¦åˆ 除 %(title)s å—?" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31 +#, python-format +msgid "Really remove %(media_title)s from %(collection_title)s?" +msgstr "确定è¦ä»Ž %(collection_title)s 移除 %(media_title)s å—?" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 +msgid "Remove" +msgstr "移除" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 +#, python-format +msgid "%(username)s's collections" +msgstr "%(username)s çš„åˆé›†" + +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 +#, python-format +msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" +msgstr "<a href=\"%(user_url)s\">%(username)s</a> çš„åˆé›†" + +#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n" +msgstr "%(username)s 您好:\n%(comment_author)s 在 %(instance_name)s 对您的内容 (%(comment_url)s) å¼ è´´è¯„è®º\n" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "%(username)s的媒体" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38 +#, python-format +msgid "" +"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " +"href=\"%(tag_url)s\">%(tag)s</a>" +msgstr "<a href=\"%(user_url)s\">%(username)s</a> 的有 <a href=\"%(tag_url)s\">%(tag)s</a> æ ‡ç¾çš„媒体" + +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 +#, 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:38 +#, python-format +msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" +msgstr "â– æµè§ˆ <a href=\"%(user_url)s\">%(username)s</a> 的媒体" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 +msgid "Add a comment" +msgstr "新增评论" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 +msgid "Add this comment" +msgstr "å¢žåŠ è¯„è®º" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "å·²å¢žåŠ " + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 +#, python-format +msgid "Add “%(media_title)s†to a collection" +msgstr "把“%(media_title)sâ€åŠ å…¥åˆé›†" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 +msgid "+" +msgstr "+" + +#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58 +msgid "Add a new collection" +msgstr "新增新的åˆé›†" + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29 +msgid "" +"You can track the state of media being processed for your gallery here." +msgstr "您å¯ä»¥åœ¨è¿™é‡Œè¿½è¸ªæ‚¨çš„艺廊ä¸åª’体处ç†çš„状æ€ã€‚" + +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89 +msgid "Your last 10 successful uploads" +msgstr "您的最近 10 次æˆåŠŸä¸Šä¼ çš„çºªå½•" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 +#, python-format +msgid "%(username)s's profile" +msgstr "%(username)s 的个人资料" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "这个地方能让您å‘他人介ç»è‡ªå·±ã€‚" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "编辑个人资料" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "这个用户(还)没有填写个人资料。" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "æµè§ˆåˆé›†" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "查看 %(username)s 的全部媒体" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "æ¤å¤„æ˜¯æ‚¨çš„åª’ä½“ä¼šå‡ºçŽ°çš„åœ°æ–¹ï¼Œä½†æ˜¯ä¼¼ä¹Žè¿˜æ²¡æœ‰åŠ å…¥ä»»ä½•ä¸œè¥¿ã€‚" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "那里好åƒè¿˜æ²¡æœ‰ä»»ä½•的媒体……" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "需è¦è®¤è¯ç”µå邮件地å€" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "快完æˆäº†ï¼ä½†æ‚¨éœ€è¦æ¿€æ´»æ‚¨çš„账户。" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "账户激活说明将在ç¨åŽé€è¾¾ã€‚" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "如果ä»ç„¶æ— 法认è¯ï¼Œæ‚¨å¯ä»¥ï¼š" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "é‡å‘认è¯é‚®ä»¶" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "有人用注册了该账户,但是该账户需è¦è¢«å¯ç”¨ã€‚" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "如果您就是本人但是未收到认è¯ä¿¡ï¼Œæ‚¨å¯ä»¥<a href=\"%(login_url)s\">登录</a>ç„¶åŽé‡å‘一次。" + +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 +msgid "(remove)" +msgstr "(移除)" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:21 +msgid "Collected in" +msgstr "åˆé›†äºŽ" + +#: mediagoblin/templates/mediagoblin/utils/collections.html:40 +msgid "Add to a collection" +msgstr "æ·»åŠ åˆ°åˆé›†" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 +msgid "feed icon" +msgstr "feed å›¾æ ‡" + +#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23 +#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23 +msgid "Atom feed" +msgstr "Atom feed" + +#: mediagoblin/templates/mediagoblin/utils/license.html:25 +msgid "All rights reserved" +msgstr "ç‰ˆæƒæ‰€æœ‰" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:39 +msgid "↠Newer" +msgstr "↠更新的" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:45 +msgid "Older →" +msgstr "æ›´æ—§çš„ →" + +#: mediagoblin/templates/mediagoblin/utils/pagination.html:48 +msgid "Go to page:" +msgstr "跳到页数:" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33 +msgid "newer" +msgstr "æ›´æ–°çš„" + +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39 +#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44 +msgid "older" +msgstr "æ›´æ—§çš„" + +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "æ ‡ç¾" + +#: mediagoblin/tools/exif.py:83 +msgid "Could not read the image file." +msgstr "æ— æ³•è¯»å–图片文件。" + +#: mediagoblin/tools/response.py:38 +msgid "Oops!" +msgstr "糟糕ï¼" + +#: mediagoblin/tools/response.py:39 +msgid "An error occured" +msgstr "å‘生错误" + +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 +msgid "Operation not allowed" +msgstr "æ“作ä¸å…许" + +#: mediagoblin/tools/response.py:64 +msgid "" +"Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " +"function that you are not allowed to. Have you been trying to delete all " +"user accounts again?" +msgstr "对ä¸èµ·è€å…„,我ä¸èƒ½è®©ä½ è¿™æ ·åšï¼</p><p>您æ£åœ¨è¯•ç€æ“作ä¸å…è®¸æ‚¨ä½¿ç”¨çš„åŠŸèƒ½ã€‚æ‚¨éš¾é“æƒ³æ‰“ç®—åˆ é™¤æ‰€æœ‰ç”¨æˆ·è´¦æˆ·å—?" + +#: mediagoblin/tools/response.py:72 +msgid "" +"There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" +" the address is correct, maybe the page you're looking for has been moved or" +" deleted." +msgstr "ä¸å¥½æ„æ€ï¼Œçœ‹èµ·æ¥è¿™ä¸ªç½‘å€ä¸Šæ²¡æœ‰ç½‘页。</p><p>å¦‚æžœæ‚¨ç¡®å®šè¿™ä¸ªç½‘å€æ˜¯æ£ç¡®çš„,您在寻找的页é¢å¯èƒ½å·²ç»ç§»åŠ¨æˆ–æ˜¯è¢«åˆ é™¤äº†ã€‚" + +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "å¹´" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "月" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "周" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "æ—¥" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "å°æ—¶" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "分钟" + +#: mediagoblin/user_pages/forms.py:23 +msgid "Comment" +msgstr "评论" + +#: mediagoblin/user_pages/forms.py:25 +msgid "" +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:31 +msgid "I am sure I want to delete this" +msgstr "我确定我è¦åˆ 除这个媒体" + +#: mediagoblin/user_pages/forms.py:35 +msgid "I am sure I want to remove this item from the collection" +msgstr "我确定我è¦ä»Žåˆé›†ä¸ç§»é™¤æ¤é¡¹ç›®" + +#: mediagoblin/user_pages/forms.py:39 +msgid "Collection" +msgstr "åˆé›†" + +#: mediagoblin/user_pages/forms.py:40 +msgid "-- Select --" +msgstr "— 请选择 —" + +#: mediagoblin/user_pages/forms.py:42 +msgid "Include a note" +msgstr "åŠ æ³¨" + +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "抱æ‰ï¼Œä¸å¼€æ”¾è¯„论。" + +#: mediagoblin/user_pages/views.py:183 +msgid "Oops, your comment was empty." +msgstr "啊,您的评论是空的。" + +#: mediagoblin/user_pages/views.py:189 +msgid "Your comment has been posted!" +msgstr "您的评论已ç»å¼ 贴完æˆï¼" + +#: mediagoblin/user_pages/views.py:225 +msgid "Please check your entries and try again." +msgstr "请检查项目并é‡è¯•。" + +#: mediagoblin/user_pages/views.py:265 +msgid "You have to select or add a collection" +msgstr "您需è¦é€‰æ‹©æˆ–是新增一个åˆé›†" + +#: mediagoblin/user_pages/views.py:276 +#, python-format +msgid "\"%s\" already in collection \"%s\"" +msgstr "“%sâ€å·²ç»åœ¨â€œ%sâ€åˆé›†" + +#: mediagoblin/user_pages/views.py:282 +#, python-format +msgid "\"%s\" added to collection \"%s\"" +msgstr "“%sâ€åŠ å…¥â€œ%sâ€åˆé›†" + +#: mediagoblin/user_pages/views.py:307 +msgid "You deleted the media." +msgstr "您已ç»åˆ 除æ¤åª’体。" + +#: mediagoblin/user_pages/views.py:319 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "由于您没有勾选确认,该媒体没有被移除。" + +#: mediagoblin/user_pages/views.py:326 +msgid "You are about to delete another user's media. Proceed with caution." +msgstr "您æ£åœ¨åˆ 除别人的媒体,请å°å¿ƒæ“作。" + +#: mediagoblin/user_pages/views.py:399 +msgid "You deleted the item from the collection." +msgstr "您已ç»ä»Žè¯¥åˆé›†ä¸åˆ 除该项目。" + +#: mediagoblin/user_pages/views.py:403 +msgid "The item was not removed because you didn't check that you were sure." +msgstr "由于您没有勾选确认,该项目没有被移除。" + +#: mediagoblin/user_pages/views.py:411 +msgid "" +"You are about to delete an item from another user's collection. Proceed with" +" caution." +msgstr "您æ£åœ¨ä»Žåˆ«äººçš„åˆé›†ä¸åˆ 除项目,请å°å¿ƒæ“作。" + +#: mediagoblin/user_pages/views.py:443 +#, python-format +msgid "You deleted the collection \"%s\"" +msgstr "您已ç»åˆ 除“%sâ€åˆé›†ã€‚" + +#: mediagoblin/user_pages/views.py:450 +msgid "" +"The collection was not deleted because you didn't check that you were sure." +msgstr "由于您没有勾选确认,该åˆé›†æ²¡æœ‰è¢«ç§»é™¤ã€‚" + +#: mediagoblin/user_pages/views.py:458 +msgid "" +"You are about to delete another user's collection. Proceed with caution." +msgstr "您æ£åœ¨åˆ 除别人的åˆé›†ï¼Œè¯·å°å¿ƒæ“作。" diff --git a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mo Binary files differindex d75d2eb2..3dabd00b 100644 --- a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po index a5e95640..60587db3 100644 --- a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po @@ -6,9 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: Chinese (Taiwan) (Big5) (http://www.transifex.com/projects/p/mediagoblin/language/zh_TW.Big5/)\n" "MIME-Version: 1.0\n" @@ -18,253 +18,264 @@ msgstr "" "Language: zh_TW.Big5\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" - -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." msgstr "" -#: mediagoblin/auth/forms.py:60 -msgid "Email address" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." msgstr "" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." msgstr "" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." msgstr "" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "" -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "" - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." msgstr "" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" msgstr "" #: mediagoblin/edit/forms.py:67 -msgid "New password" +msgid "Enable insite notifications about events." msgstr "" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "" - -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." msgstr "" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." msgstr "" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " @@ -272,15 +283,202 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "" @@ -290,6 +488,10 @@ msgstr "" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "" @@ -344,7 +546,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" msgstr "" @@ -357,215 +559,327 @@ msgid "Your OAuth clients" msgstr "" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 -msgid "Invalid file given for media type." +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." msgstr "" -#: mediagoblin/submit/forms.py:26 -msgid "File" +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" msgstr "" -#: mediagoblin/submit/views.py:51 -msgid "You must provide a file." +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" msgstr "" -#: mediagoblin/submit/views.py:97 -msgid "Woohoo! Submitted!" +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/plugins/openid/views.py:106 #, python-format -msgid "Collection \"%s\" added!" +msgid "Verification of %s failed: %s" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 -msgid "Verify your email!" +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 -msgid "log out" +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 #: mediagoblin/templates/mediagoblin/auth/login.html:28 #: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 msgid "Log in" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:79 -#, python-format -msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 -msgid "Change account settings" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 -msgid "Media processing panel" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 -msgid "Add media" +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 -#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 -msgid "Create new collection" +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:144 msgid "" -"Powered by <a href=\"http://mediagoblin.org/\" title='Version " -"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +"You can't delete your only Persona email address unless you have a password " +"set." msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:176 msgid "" -"Released under the <a " -"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " -"href=\"%(source_link)s\">Source code</a> available." +"Sorry, an account is already registered with that Persona email address." +msgstr "" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "" + +#: mediagoblin/processing/__init__.py:420 +msgid "Invalid file given for media type." +msgstr "" + +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "" + +#: mediagoblin/submit/forms.py:34 +msgid "File" +msgstr "" + +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/submit/views.py:55 +msgid "You must provide a file." msgstr "" +#: mediagoblin/submit/views.py:69 +msgid "Woohoo! Submitted!" +msgstr "" + +#: mediagoblin/submit/views.py:138 +#, python-format +msgid "Collection \"%s\" added!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "" + +#: mediagoblin/templates/mediagoblin/banned.html:24 #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " -"extraordinarily great piece of media hosting software." +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:36 -msgid "" -"To add your own media, place comments, and more, you can log in with your " -"MediaGoblin account." +#: mediagoblin/templates/mediagoblin/base.html:81 +msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Don't have one yet? It's easy!" +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" or\n" -" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:47 -msgid "Most recent media" +#: mediagoblin/templates/mediagoblin/base.html:122 +msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 +msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:135 +msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 +msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" +#: mediagoblin/templates/mediagoblin/base.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 +msgid "Create new collection" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" msgstr "" -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format -msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" -"\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" msgstr "" #: mediagoblin/templates/mediagoblin/auth/register.html:28 @@ -573,7 +887,7 @@ msgstr "" msgid "Create an account!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 +#: mediagoblin/templates/mediagoblin/auth/register.html:41 msgid "Create" msgstr "" @@ -588,6 +902,62 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by <a href=\"http://mediagoblin.org/\" title='Version " +"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the <a " +"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a " +"href=\"%(source_link)s\">Source code</a> available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 +msgid "" +"To add your own media, place comments, and more, you can log in with your " +"MediaGoblin account." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 +msgid "" +"\n" +" >Create an account at this site</a>\n" +" or" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 +msgid "" +"\n" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -600,13 +970,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "" @@ -623,12 +993,18 @@ msgstr "" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -639,7 +1015,7 @@ msgid "Yes, really delete my account" msgstr "" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "" @@ -656,10 +1032,14 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -671,6 +1051,39 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 @@ -681,8 +1094,8 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "" @@ -705,7 +1118,8 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "" @@ -713,6 +1127,11 @@ msgstr "" msgid "WebM file (Vorbis codec)" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -723,70 +1142,267 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" msgstr "" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." msgstr "" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "" @@ -805,11 +1421,6 @@ msgstr "" msgid "Edit" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -821,7 +1432,7 @@ msgstr "" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "" @@ -864,23 +1475,20 @@ msgstr "" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -906,85 +1514,107 @@ msgstr "" msgid "Your last 10 successful uploads" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 -#, python-format -msgid "%(username)s's profile" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 -msgid "Email verification needed" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 -msgid "Almost done! Your account still needs to be activated." +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format msgid "" -"An email should arrive in a few moments with instructions on how to do so." -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 -msgid "In case it doesn't:" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 -msgid "Resend verification email" +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 -msgid "" -"Someone has registered an account with this username, but it still has to be" -" activated." -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format -msgid "" -"If you are that person but you've lost your verification email, you can <a " -"href=\"%(login_url)s\">log in</a> and resend it." +msgid "%(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "Edit profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 msgid "Browse collections" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 #, python-format msgid "View all of %(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 #: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 msgid "There doesn't seem to be any media here yet..." msgstr "" +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 +msgid "Email verification needed" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 +msgid "Almost done! Your account still needs to be activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 +msgid "" +"An email should arrive in a few moments with instructions on how to do so." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 +msgid "In case it doesn't:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 +msgid "Resend verification email" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 +msgid "" +"Someone has registered an account with this username, but it still has to be" +" activated." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 +#, python-format +msgid "" +"If you are that person but you've lost your verification email, you can <a " +"href=\"%(login_url)s\">log in</a> and resend it." +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr "" @@ -1033,49 +1663,84 @@ msgstr "" msgid "older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" msgstr "" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." msgstr "" #: mediagoblin/user_pages/forms.py:31 @@ -1098,73 +1763,84 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo Binary files differindex 3d267cfc..35beea63 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 bd50df78..67b41aba 100644 --- a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po @@ -3,17 +3,19 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# <chc@citi.sinica.edu.tw>, 2011. -# Harry Chen <harryhow@gmail.com>, 2011-2012. -# <medicalwei@gmail.com>, 2012. +# <chc@citi.sinica.edu.tw>, 2011 +# Harry Chen <harryhow@gmail.com>, 2011-2012 +# medicalwei <medicalwei@gmail.com>, 2013 +# medicalwei <medicalwei@gmail.com>, 2012 +# m13253 <m13253@hotmail.com>, 2013 msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" -"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n" -"POT-Creation-Date: 2013-03-04 18:04-0600\n" -"PO-Revision-Date: 2013-03-05 00:04+0000\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2013-12-03 13:23-0600\n" +"PO-Revision-Date: 2013-12-03 19:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/mediagoblin/language/zh_TW/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -21,269 +23,467 @@ msgstr "" "Language: zh_TW\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "" +#: mediagoblin/decorators.py:300 mediagoblin/plugins/openid/views.py:202 +msgid "Sorry, registration is disabled on this instance." +msgstr "抱æ‰ï¼Œæœ¬ç«™å·²ç¶“關閉註冊功能。" -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "" +#: mediagoblin/decorators.py:315 +msgid "Sorry, reporting is disabled on this instance." +msgstr "抱æ‰ï¼Œæœ¬ç«™å·²ç¶“é—œé–‰å›žå ±åŠŸèƒ½ã€‚" -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "" +#: mediagoblin/decorators.py:358 mediagoblin/plugins/ldap/views.py:55 +#: mediagoblin/plugins/persona/views.py:77 +msgid "Sorry, authentication is disabled on this instance." +msgstr "抱æ‰ï¼Œæœ¬ç«™å·²ç¶“關閉èªè¨¼ã€‚" -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 -msgid "Username" -msgstr "使用者å稱" - -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 -msgid "Password" -msgstr "密碼" - -#: mediagoblin/auth/forms.py:60 -msgid "Email address" -msgstr "Email ä½å€" +#: mediagoblin/auth/tools.py:43 +msgid "Invalid User name or email address." +msgstr "無效的使用者å稱或 email ä½ç½®ã€‚" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" -msgstr "使用者å稱或 email" +#: mediagoblin/auth/tools.py:44 +msgid "This field does not take email addresses." +msgstr "本欄ä½ä¸æŽ¥å— email ä½ç½®ã€‚" -#: mediagoblin/auth/views.py:54 -msgid "Sorry, registration is disabled on this instance." -msgstr "抱æ‰ï¼Œæœ¬ç«™å·²ç¶“æš«åœè¨»å†Šã€‚" +#: mediagoblin/auth/tools.py:45 +msgid "This field requires an email address." +msgstr "本欄ä½éœ€è¦ email ä½ç½®ã€‚" -#: mediagoblin/auth/views.py:68 +#: mediagoblin/auth/tools.py:116 msgid "Sorry, a user with that name already exists." msgstr "抱æ‰ï¼Œé€™å€‹ä½¿ç”¨è€…å稱已經å˜åœ¨ã€‚" -#: mediagoblin/auth/views.py:72 +#: mediagoblin/auth/tools.py:120 mediagoblin/edit/views.py:402 msgid "Sorry, a user with that email address already exists." msgstr "抱æ‰ï¼Œæ¤ email ä½ç½®å·²ç¶“被註冊了。" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:142 mediagoblin/edit/views.py:358 +#: mediagoblin/edit/views.py:379 mediagoblin/plugins/basic_auth/views.py:110 +msgid "The verification key or user id is incorrect." +msgstr "èªè¨¼é‡‘鑰或使用者 ID 䏿£ç¢ºã€‚" + +#: mediagoblin/auth/views.py:161 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "您的 email ä½å€å·²è¢«èªè‰ã€‚您已經å¯ä»¥ç™»å…¥ï¼Œç·¨è¼¯æ‚¨çš„個人檔案並上傳圖片ï¼" -#: mediagoblin/auth/views.py:180 +#: mediagoblin/auth/views.py:167 msgid "The verification key or user id is incorrect" msgstr "èªè‰ç¢¼æˆ–是使用者 ID 錯誤" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:185 msgid "You must be logged in so we know who to send the email to!" msgstr "æ‚¨å¿…é ˆç™»å…¥ï¼Œæˆ‘å€‘æ‰çŸ¥é“ä¿¡è¦é€çµ¦èª°ï¼" -#: mediagoblin/auth/views.py:206 +#: mediagoblin/auth/views.py:193 msgid "You've already verified your email address!" msgstr "您的電å郵件已經確èªäº†ï¼" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:203 msgid "Resent your verification email." msgstr "é‡é€èªè‰ä¿¡ã€‚" -#: mediagoblin/auth/views.py:250 -msgid "" -"If that email address (case sensitive!) is registered an email has been sent" -" with instructions on how to change your password." -msgstr "" - -#: mediagoblin/auth/views.py:261 -msgid "Couldn't find someone with that username." -msgstr "" - -#: mediagoblin/auth/views.py:264 -msgid "" -"An email has been sent with instructions on how to change your password." -msgstr "修改密碼的指示已經由電å郵件寄é€åˆ°æ‚¨çš„信箱。" - -#: mediagoblin/auth/views.py:271 -msgid "" -"Could not send password recovery email as your username is inactive or your " -"account's email address has not been verified." -msgstr "無法傳é€å¯†ç¢¼å›žå¾©ä¿¡ä»¶ï¼Œå› 為您的使用者å稱已失效或是帳號尚未èªè‰ã€‚" - -#: mediagoblin/auth/views.py:328 -msgid "You can now log in using your new password." -msgstr "您ç¾åœ¨å¯ä»¥ç”¨æ–°çš„密碼登入了ï¼" - -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 -#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 +#: mediagoblin/edit/forms.py:27 mediagoblin/edit/forms.py:87 +#: mediagoblin/submit/forms.py:37 mediagoblin/submit/forms.py:61 #: mediagoblin/user_pages/forms.py:45 msgid "Title" msgstr "標題" -#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:40 msgid "Description of this work" msgstr "這個作å“çš„æè¿°" -#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52 -#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32 -#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 +#: mediagoblin/edit/forms.py:31 mediagoblin/edit/forms.py:54 +#: mediagoblin/edit/forms.py:91 mediagoblin/submit/forms.py:65 msgid "" "You can use\n" " <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" " Markdown</a> for formatting." -msgstr "您å¯ä»¥ç”¨ <a href=\"http://markdown.tw\">Markdown</a> 來排版。" +msgstr "您å¯ä»¥ä½¿ç”¨\n<a href=\"http://markdown.tw\">\nMarkdown</a> 來排版。" -#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 +#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:45 msgid "Tags" msgstr "標籤" -#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 +#: mediagoblin/edit/forms.py:37 mediagoblin/submit/forms.py:47 msgid "Separate tags by commas." msgstr "用逗號分隔標籤。" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:40 mediagoblin/edit/forms.py:95 msgid "Slug" msgstr "簡稱" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:41 mediagoblin/edit/forms.py:96 msgid "The slug can't be empty" msgstr "簡稱ä¸èƒ½ç‚ºç©ºç™½" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "" "The title part of this media's address. You usually don't need to change " "this." msgstr "æ¤åª’體網å€çš„æ¨™é¡Œéƒ¨ä»½ã€‚通常ä¸éœ€è¦ä¿®æ”¹ã€‚" -#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41 +#: mediagoblin/edit/forms.py:46 mediagoblin/submit/forms.py:50 #: mediagoblin/templates/mediagoblin/utils/license.html:20 msgid "License" msgstr "授權" -#: mediagoblin/edit/forms.py:50 +#: mediagoblin/edit/forms.py:52 msgid "Bio" msgstr "自我介紹" -#: mediagoblin/edit/forms.py:56 +#: mediagoblin/edit/forms.py:58 msgid "Website" msgstr "網站" -#: mediagoblin/edit/forms.py:58 +#: mediagoblin/edit/forms.py:60 msgid "This address contains errors" msgstr "本網å€å‡ºéŒ¯äº†" -#: mediagoblin/edit/forms.py:63 -msgid "Old password" -msgstr "舊的密碼" - -#: mediagoblin/edit/forms.py:64 -msgid "Enter your old password to prove you own this account." -msgstr "è¼¸å…¥æ‚¨çš„èˆŠå¯†ç¢¼ä¾†è‰æ˜Žæ‚¨æ“有這個帳號。" +#: mediagoblin/edit/forms.py:65 +msgid "Email me when others comment on my media" +msgstr "ç•¶æœ‰äººå°æˆ‘的媒體評論時寄信給我" #: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "新密碼" +msgid "Enable insite notifications about events." +msgstr "啟用活動的站內通知。" -#: mediagoblin/edit/forms.py:74 +#: mediagoblin/edit/forms.py:69 msgid "License preference" -msgstr "" +msgstr "授權å好" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:75 msgid "This will be your default license on upload forms." -msgstr "" - -#: mediagoblin/edit/forms.py:82 -msgid "Email me when others comment on my media" -msgstr "ç•¶æœ‰äººå°æˆ‘的媒體評論時寄信給我" +msgstr "在上傳é é¢ï¼Œé€™å°‡æœƒæ˜¯æ‚¨é è¨çš„æŽˆæ¬Šæ¨¡å¼ã€‚" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:88 msgid "The title can't be empty" msgstr "標題ä¸èƒ½æ˜¯ç©ºçš„" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:90 mediagoblin/submit/forms.py:64 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "這個è’è—çš„æè¿°" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:97 msgid "" "The title part of this collection's address. You usually don't need to " "change this." msgstr "æ¤è’è—ç¶²å€çš„æ¨™é¡Œéƒ¨ä»½ï¼Œé€šå¸¸ä¸éœ€è¦ä¿®æ”¹ã€‚" -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:104 mediagoblin/plugins/basic_auth/forms.py:68 +msgid "Old password" +msgstr "舊的密碼" + +#: mediagoblin/edit/forms.py:106 mediagoblin/plugins/basic_auth/forms.py:70 +msgid "Enter your old password to prove you own this account." +msgstr "è¼¸å…¥æ‚¨çš„èˆŠå¯†ç¢¼ä¾†è‰æ˜Žæ‚¨æ“有這個帳號。" + +#: mediagoblin/edit/forms.py:109 mediagoblin/plugins/basic_auth/forms.py:73 +msgid "New password" +msgstr "新密碼" + +#: mediagoblin/edit/forms.py:117 +msgid "New email address" +msgstr "æ–°çš„ email ä½å€" + +#: mediagoblin/edit/forms.py:121 mediagoblin/plugins/basic_auth/forms.py:28 +#: mediagoblin/plugins/basic_auth/forms.py:43 +#: mediagoblin/plugins/ldap/forms.py:39 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:64 +#: mediagoblin/tests/test_util.py:110 +msgid "Password" +msgstr "密碼" + +#: mediagoblin/edit/forms.py:123 +msgid "Enter your password to prove you own this account." +msgstr "è¼¸å…¥æ‚¨çš„å¯†ç¢¼ä¾†è‰æ˜Žæ‚¨æ“有這個帳號。" + +#: mediagoblin/edit/views.py:73 msgid "An entry with that slug already exists for this user." -msgstr "這個簡稱已經被其他人用了" +msgstr "é€™å€‹ä½¿ç”¨è€…å·²ç¶“æœ‰ä½¿ç”¨è©²ç°¡ç¨±çš„é …ç›®äº†ã€‚" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:91 msgid "You are editing another user's media. Proceed with caution." msgstr "您æ£åœ¨ä¿®æ”¹åˆ¥äººçš„媒體,請å°å¿ƒæ“作。" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:161 #, python-format msgid "You added the attachment %s!" msgstr "æ‚¨åŠ ä¸Šäº†é™„ä»¶ã€Œ%sã€ï¼" -#: mediagoblin/edit/views.py:182 +#: mediagoblin/edit/views.py:188 msgid "You can only edit your own profile." -msgstr "" +msgstr "您åªèƒ½ä¿®æ”¹æ‚¨è‡ªå·±çš„個人檔案。" -#: mediagoblin/edit/views.py:188 +#: mediagoblin/edit/views.py:194 msgid "You are editing a user's profile. Proceed with caution." msgstr "您æ£åœ¨ä¿®æ”¹åˆ¥äººçš„個人檔案,請å°å¿ƒæ“作。" -#: mediagoblin/edit/views.py:204 +#: mediagoblin/edit/views.py:210 msgid "Profile changes saved" msgstr "個人檔案修改已儲å˜" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "密碼錯誤" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:243 msgid "Account settings saved" msgstr "帳號è¨å®šå·²å„²å˜" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:277 msgid "You need to confirm the deletion of your account." -msgstr "" +msgstr "æ‚¨å¿…é ˆè¦ç¢ºèªæ˜¯å¦åˆªé™¤æ‚¨çš„帳號。" -#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142 -#: mediagoblin/user_pages/views.py:214 +#: mediagoblin/edit/views.py:313 mediagoblin/submit/views.py:132 +#: mediagoblin/user_pages/views.py:242 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "您已經有一個稱åšã€Œ%sã€çš„è’è—了ï¼" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:317 msgid "A collection with that slug already exists for this user." msgstr "這個使用者已經有使用該簡稱的è’è—了。" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:332 msgid "You are editing another user's collection. Proceed with caution." msgstr "您æ£åœ¨ä¿®æ”¹åˆ¥äººçš„è’è—,請å°å¿ƒæ“作。" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:373 +msgid "Your email address has been verified." +msgstr "您的 email ä½å€å·²èªè¨¼ã€‚" + +#: mediagoblin/edit/views.py:408 mediagoblin/plugins/basic_auth/views.py:200 +msgid "Wrong password" +msgstr "密碼錯誤" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "無法連çµä½ˆæ™¯â€¦æ²’有æ¤ä½ˆæ™¯\n" -#: mediagoblin/gmg_commands/theme.py:71 +#: mediagoblin/gmg_commands/assetlink.py:73 msgid "No asset directory for this theme\n" msgstr "æ¤ä½ˆæ™¯æ²’æœ‰ç´ æç›®éŒ„\n" -#: mediagoblin/gmg_commands/theme.py:74 +#: mediagoblin/gmg_commands/assetlink.py:76 msgid "However, old link directory symlink found; removed.\n" msgstr "但是舊的目錄連çµå·²ç¶“找到並移除。\n" +#: mediagoblin/gmg_commands/assetlink.py:112 +#, python-format +msgid "Could not link \"%s\": %s exists and is not a symlink\n" +msgstr "無法連çµã€Œ%sã€ï¼š%s å˜åœ¨ï¼Œä¸”䏿˜¯ç¬¦è™Ÿé€£çµ\n" + +#: mediagoblin/gmg_commands/assetlink.py:119 +#, python-format +msgid "Skipping \"%s\"; already set up.\n" +msgstr "è·³éŽã€Œ%sã€ï¼Œå·²ç¶“建置完æˆã€‚\n" + +#: mediagoblin/gmg_commands/assetlink.py:124 +#, python-format +msgid "Old link found for \"%s\"; removing.\n" +msgstr "找到「%sã€èˆŠçš„連çµï¼Œåˆªé™¤ä¸ã€‚\n" + #: mediagoblin/meddleware/csrf.py:134 msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.<br/>Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "跨網站å˜å– (CSRF) çš„ cookie ä¸å˜åœ¨ï¼Œæœ‰å¯èƒ½æ˜¯ cookie 阻擋程å¼ä¹‹é¡žçš„程å¼å°Žè‡´çš„。<br/>è«‹å…許æ¤ç¶²åŸŸçš„ cookie è¨å®šã€‚" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:78 +#: mediagoblin/media_types/__init__.py:100 msgid "Sorry, I don't support that file type :(" msgstr "抱æ‰ï¼Œæˆ‘䏿”¯æ´é€™æ¨£çš„æª”æ¡ˆæ ¼å¼ :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:142 +msgid "unoconv failing to run, check log file" +msgstr "unoconv 無法執行,請檢查紀錄檔" + +#: mediagoblin/media_types/video/processing.py:44 msgid "Video transcoding failed" msgstr "å½±åƒè½‰ç¢¼å¤±æ•—" +#: mediagoblin/moderation/forms.py:21 +msgid "Take away privilege" +msgstr "移除權é™" + +#: mediagoblin/moderation/forms.py:22 +msgid "Ban the user" +msgstr "å°éŽ–è©²ä½¿ç”¨è€…" + +#: mediagoblin/moderation/forms.py:23 +msgid "Send the user a message" +msgstr "寄訊æ¯åˆ°è©²ä½¿ç”¨è€…" + +#: mediagoblin/moderation/forms.py:24 +msgid "Delete the content" +msgstr "刪除內容" + +#: mediagoblin/moderation/forms.py:53 mediagoblin/moderation/forms.py:118 +msgid "User will be banned until:" +msgstr "該使用者將被å°éŽ–ï¼Œç›´åˆ°ï¼š" + +#: mediagoblin/moderation/forms.py:57 +msgid "Why are you banning this User?" +msgstr "為什麼您è¦å°éŽ–è©²ä½¿ç”¨è€…ï¼Ÿ" + +#: mediagoblin/moderation/forms.py:109 +msgid "What action will you take to resolve the report?" +msgstr "è«‹å•æ‚¨è¦å¦‚何處ç†é€™é …å›žå ±ï¼Ÿ" + +#: mediagoblin/moderation/forms.py:115 +msgid "What privileges will you take away?" +msgstr "您è¦å–走他哪些權é™ï¼Ÿ" + +#: mediagoblin/moderation/tools.py:91 +msgid "Warning from" +msgstr "è¦å‘Šï¼Œä¾†è‡ª" + +#: mediagoblin/notifications/tools.py:54 mediagoblin/user_pages/lib.py:60 +msgid "commented on your post" +msgstr "在您的內容張貼評論" + +#: mediagoblin/notifications/views.py:35 +#, python-format +msgid "Subscribed to comments on %s!" +msgstr "已訂閱 %s 的評論ï¼" + +#: mediagoblin/notifications/views.py:48 +#, python-format +msgid "You will not receive notifications for comments on %s." +msgstr "æ‚¨å°‡ä¸æœƒæ”¶åˆ° %s 的評論通知。" + +#: mediagoblin/oauth/views.py:239 +msgid "Must provide an oauth_token." +msgstr "å¿…é ˆæä¾› oauth_token。" + +#: mediagoblin/oauth/views.py:244 mediagoblin/oauth/views.py:294 +msgid "No request token found." +msgstr "找ä¸åˆ°è«‹æ±‚çš„ token。" + +#: mediagoblin/plugins/api/views.py:75 mediagoblin/plugins/piwigo/views.py:155 +#: mediagoblin/submit/views.py:78 +msgid "Sorry, the file size is too big." +msgstr "抱æ‰ï¼Œæª”案太大了。" + +#: mediagoblin/plugins/api/views.py:78 mediagoblin/plugins/piwigo/views.py:158 +#: mediagoblin/submit/views.py:81 +msgid "Sorry, uploading this file will put you over your upload limit." +msgstr "抱æ‰ï¼Œä¸Šå‚³è©²æª”æ¡ˆå°‡æœƒè¶…éŽæ‚¨çš„上傳é™åˆ¶ã€‚" + +#: mediagoblin/plugins/api/views.py:82 mediagoblin/plugins/piwigo/views.py:162 +#: mediagoblin/submit/views.py:87 +msgid "Sorry, you have reached your upload limit." +msgstr "抱æ‰ï¼Œæ‚¨å·²ç¶“碰到了您的上傳é™åˆ¶ã€‚" + +#: mediagoblin/plugins/basic_auth/forms.py:24 +#: mediagoblin/plugins/ldap/forms.py:35 mediagoblin/plugins/openid/forms.py:27 +#: mediagoblin/plugins/persona/forms.py:24 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:76 +msgid "Username" +msgstr "使用者å稱" + +#: mediagoblin/plugins/basic_auth/forms.py:32 +#: mediagoblin/plugins/ldap/forms.py:28 mediagoblin/plugins/openid/forms.py:31 +#: mediagoblin/plugins/persona/forms.py:28 +#: mediagoblin/plugins/persona/forms.py:39 +msgid "Email address" +msgstr "Email ä½å€" + +#: mediagoblin/plugins/basic_auth/forms.py:39 +msgid "Username or Email" +msgstr "使用者å稱或 email" + +#: mediagoblin/plugins/basic_auth/forms.py:46 +msgid "Stay logged in" +msgstr "ä¿æŒç™»å…¥" + +#: mediagoblin/plugins/basic_auth/forms.py:51 +msgid "Username or email" +msgstr "使用者å稱或 email" + +#: mediagoblin/plugins/basic_auth/views.py:54 +msgid "" +"If that email address (case sensitive!) is registered an email has been sent" +" with instructions on how to change your password." +msgstr "如果那 email ä½ç½® (請注æ„大å°å¯«) 已經註冊,寫有修改密碼æ¥é©Ÿçš„ email 已經é€å‡ºã€‚" + +#: mediagoblin/plugins/basic_auth/views.py:65 +msgid "Couldn't find someone with that username." +msgstr "找ä¸åˆ°ç›¸é—œçš„使用者å稱。" + +#: mediagoblin/plugins/basic_auth/views.py:68 +msgid "" +"An email has been sent with instructions on how to change your password." +msgstr "修改密碼的指示已經由電å郵件寄é€åˆ°æ‚¨çš„信箱。" + +#: mediagoblin/plugins/basic_auth/views.py:75 +msgid "" +"Could not send password recovery email as your username is inactive or your " +"account's email address has not been verified." +msgstr "無法傳é€å¯†ç¢¼å›žå¾©ä¿¡ä»¶ï¼Œå› 為您的使用者å稱已失效或是帳號尚未èªè‰ã€‚" + +#: mediagoblin/plugins/basic_auth/views.py:123 +msgid "The user id is incorrect." +msgstr "使用者 ID 䏿£ç¢º" + +#: mediagoblin/plugins/basic_auth/views.py:139 +msgid "You can now log in using your new password." +msgstr "您ç¾åœ¨å¯ä»¥ç”¨æ–°çš„密碼登入了ï¼" + +#: mediagoblin/plugins/basic_auth/views.py:163 +msgid "" +"You are no longer an active user. Please contact the system admin to " +"reactivate your account." +msgstr "您ç¾åœ¨ä¸æ˜¯æ´»å‹•ä¸çš„使用者,請è¯çµ¡ç³»çµ±ç®¡ç†å“¡ä»¥é‡æ–°å•Ÿç”¨æ‚¨çš„帳號。" + +#: mediagoblin/plugins/basic_auth/views.py:215 +msgid "Your password was changed successfully" +msgstr "您的密碼已經æˆåŠŸä¿®æ”¹" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:36 +msgid "Set your new password" +msgstr "è¨å®šæ‚¨çš„æ–°å¯†ç¢¼" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html:39 +msgid "Set password" +msgstr "è¨å®šæ–°å¯†ç¢¼" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:28 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "更改 %(username)s 的密碼" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html:45 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:40 +msgid "Save" +msgstr "儲å˜" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:22 +msgid "Don't have an account yet?" +msgstr "還沒有帳號嗎?" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html:24 +msgid "Create one here!" +msgstr "在這裡建立一個å§ï¼" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html:22 +msgid "Change your password." +msgstr "更改您的密碼。" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:23 +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:31 +msgid "Recover password" +msgstr "找回密碼" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html:34 +msgid "Send instructions" +msgstr "é€å‡ºæŒ‡ç¤º" + +#: mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html:22 +msgid "Forgot your password?" +msgstr "忘了密碼嗎?" + #: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24 msgid "Location" msgstr "ä½ç½®" @@ -293,6 +493,10 @@ msgstr "ä½ç½®" msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>" msgstr "在 <a href=\"%(osm_url)s\">OpenStreetMap</a> 上觀看" +#: mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html:22 +msgid "Sign in to create an account!" +msgstr "登入以建立帳號ï¼" + #: mediagoblin/plugins/oauth/forms.py:29 msgid "Allow" msgstr "å…許" @@ -307,7 +511,7 @@ msgstr "å稱" #: mediagoblin/plugins/oauth/forms.py:35 msgid "The name of the OAuth client" -msgstr "OAuth client çš„å稱" +msgstr "OAuth 用戶程å¼çš„å稱" #: mediagoblin/plugins/oauth/forms.py:36 msgid "Description" @@ -331,7 +535,7 @@ msgid "" " <strong>Public</strong> - The client can't make confidential\n" " requests to the GNU MediaGoblin instance (e.g. client-side\n" " JavaScript client)." -msgstr "<strong>秘密</strong> — OAuth client å¯ä»¥å° GNU MediaGoblin ç«™å°ç™¼é€ä¸è¢«ä½¿ç”¨è€…ä»£ç†æ””截的請求 (例如伺æœç«¯çš„ client)。\n<strong>公開</strong> — OAuth client ç„¡æ³•å° GNU MediaGoblin ç«™å°ç™¼é€ç§˜å¯†çš„請求 (例如客戶端的 JavaScript client)。" +msgstr "<strong>秘密</strong> — OAuth 用戶程å¼å¯ä»¥å° GNU MediaGoblin ç«™å°ç™¼é€ä¸è¢«ä½¿ç”¨è€…ä»£ç†æ””截的請求 (例如伺æœç«¯çš„用戶程å¼)。\n<strong>公開</strong> — OAuth 用戶程å¼ç„¡æ³•å° GNU MediaGoblin ç«™å°ç™¼é€ç§˜å¯†çš„請求 (例如客戶端的 JavaScript 用戶程å¼)。" #: mediagoblin/plugins/oauth/forms.py:52 msgid "Redirect URI" @@ -341,107 +545,376 @@ msgstr "é‡å®šå‘ URI" msgid "" "The redirect URI for the applications, this field\n" " is <strong>required</strong> for public clients." -msgstr "æ¤æ‡‰ç”¨ç¨‹å¼çš„é‡å®šå‘ URI,本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„ OAuth client 為必填。" +msgstr "æ¤æ‡‰ç”¨ç¨‹å¼çš„é‡å®šå‘ URI,本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„ OAuth 用戶程å¼ç‚ºå¿…填。" #: mediagoblin/plugins/oauth/forms.py:66 msgid "This field is required for public clients" -msgstr "本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„ OAuth client 為必填" +msgstr "本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„用戶程å¼ç‚ºå¿…å¡«" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:55 msgid "The client {0} has been registered!" -msgstr "OAuth client {0} 註冊完æˆï¼" +msgstr "OAuth ç”¨æˆ¶ç¨‹å¼ {0} 註冊完æˆï¼" #: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22 msgid "OAuth client connections" -msgstr "" +msgstr "OAuth 用戶程å¼é€£ç·š" #: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22 msgid "Your OAuth clients" -msgstr "" +msgstr "您的 OAuth 用戶程å¼" #: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:39 #: mediagoblin/templates/mediagoblin/submit/collection.html:30 -#: mediagoblin/templates/mediagoblin/submit/start.html:34 +#: mediagoblin/templates/mediagoblin/submit/start.html:39 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" msgstr "å¢žåŠ " -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/plugins/openid/__init__.py:97 +#: mediagoblin/plugins/openid/views.py:268 +#: mediagoblin/plugins/openid/views.py:297 +msgid "Sorry, an account is already registered to that OpenID." +msgstr "抱æ‰ï¼Œæœ‰å¸³è™Ÿå·²ç¶“登記了您輸入的 OpenID。" + +#: mediagoblin/plugins/openid/forms.py:38 +msgid "OpenID" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/views.py:48 +msgid "Sorry, the OpenID server could not be found" +msgstr "抱æ‰ï¼Œæ‰¾ä¸åˆ° OpenID 伺æœå™¨" + +#: mediagoblin/plugins/openid/views.py:61 +#, python-format +msgid "No OpenID service was found for %s" +msgstr "找ä¸åˆ° %s çš„ OpenID æœå‹™" + +#: mediagoblin/plugins/openid/views.py:106 +#, python-format +msgid "Verification of %s failed: %s" +msgstr "%s çš„èªè¨¼å¤±æ•—:%s" + +#: mediagoblin/plugins/openid/views.py:117 +msgid "Verification cancelled" +msgstr "èªè¨¼å·²å–消" + +#: mediagoblin/plugins/openid/views.py:314 +msgid "Your OpenID url was saved successfully." +msgstr "您的 OpenID url å·²æˆåŠŸå„²å˜ã€‚" + +#: mediagoblin/plugins/openid/views.py:338 +#: mediagoblin/plugins/openid/views.py:393 +msgid "You can't delete your only OpenID URL unless you have a password set" +msgstr "é™¤éžæ‚¨è¨å®šäº†å¸³è™Ÿçš„密碼,您無法刪除帳號下唯一的 OpenID URL" + +#: mediagoblin/plugins/openid/views.py:343 +#: mediagoblin/plugins/openid/views.py:402 +msgid "That OpenID is not registered to this account." +msgstr "OpenID 尚未登記到æ¤å¸³è™Ÿ" + +#: mediagoblin/plugins/openid/views.py:385 +msgid "OpenID was successfully removed." +msgstr "OpenID å·²æˆåŠŸç§»é™¤ã€‚" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:31 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:34 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:23 +msgid "Add an OpenID" +msgstr "新增 OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html:34 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:23 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:31 +msgid "Delete an OpenID" +msgstr "刪除 OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html:39 +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:39 +#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 +msgid "Delete" +msgstr "刪除" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html:21 +msgid "OpenID's" +msgstr "OpenID" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:28 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:36 +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:57 +#: mediagoblin/templates/mediagoblin/base.html:106 +#: mediagoblin/templates/mediagoblin/auth/login.html:28 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 +#: mediagoblin/templates/mediagoblin/auth/login.html:47 +msgid "Log in" +msgstr "登入" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:39 +#: mediagoblin/templates/mediagoblin/auth/login.html:39 +msgid "Logging in failed!" +msgstr "登入失敗ï¼" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:44 +msgid "Log in to create an account!" +msgstr "登入以創建一個帳號ï¼" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html:51 +msgid "Or login with a password!" +msgstr "或是使用密碼登入ï¼" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html:23 +msgid "Or login with OpenID!" +msgstr "或是使用 OpenID 登入ï¼" + +#: mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html:23 +msgid "Or register with OpenID!" +msgstr "或是使用 OpenID 註冊ï¼" + +#: mediagoblin/plugins/persona/__init__.py:90 +msgid "Sorry, an account is already registered to that Persona email." +msgstr "抱æ‰ï¼Œæœ‰å¸³è™Ÿå·²ç¶“登記了您輸入的 Persona email。" + +#: mediagoblin/plugins/persona/views.py:138 +msgid "The Persona email address was successfully removed." +msgstr "Persona email ä½å€å·²æˆåŠŸç§»é™¤ã€‚" + +#: mediagoblin/plugins/persona/views.py:144 +msgid "" +"You can't delete your only Persona email address unless you have a password " +"set." +msgstr "é™¤éžæ‚¨è¨å®šäº†å¸³è™Ÿçš„密碼,您無法刪除帳號下唯一的 Persona email ä½å€ã€‚" + +#: mediagoblin/plugins/persona/views.py:149 +msgid "That Persona email address is not registered to this account." +msgstr "該 Persona email ä½å€å°šæœªç™»è¨˜åˆ°æ¤å¸³è™Ÿã€‚" + +#: mediagoblin/plugins/persona/views.py:176 +msgid "" +"Sorry, an account is already registered with that Persona email address." +msgstr "抱æ‰ï¼Œæœ‰å¸³è™Ÿå·²ç¶“登記了您輸入的 Persona email ä½å€ã€‚" + +#: mediagoblin/plugins/persona/views.py:192 +msgid "Your Persona email address was saved successfully." +msgstr "您的 Persona email ä½å€å·²æˆåŠŸå„²å˜" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:31 +msgid "Delete a Persona email address" +msgstr "刪除 Persona email ä½å€" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html:34 +msgid "Add a Persona email address" +msgstr "新增 Persona email ä½å€" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html:21 +msgid "Persona's" +msgstr "Persona çš„" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html:22 +msgid "Or login with Persona!" +msgstr "或是使用 Persona 登入ï¼" + +#: mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html:22 +msgid "Or register with Persona!" +msgstr "或是使用 Persona 註冊ï¼" + +#: mediagoblin/processing/__init__.py:420 msgid "Invalid file given for media type." msgstr "指定錯誤的媒體類別ï¼" -#: mediagoblin/submit/forms.py:26 +#: mediagoblin/processing/__init__.py:427 +msgid "Copying to public storage failed." +msgstr "複製到公有å˜å„²å¤±æ•—。" + +#: mediagoblin/processing/__init__.py:435 +msgid "An acceptable processing file was not found" +msgstr "找ä¸åˆ°å¯æ”¶å—çš„å¾…è™•ç†æª”案" + +#: mediagoblin/submit/forms.py:30 +msgid "Max file size: {0} mb" +msgstr "最大檔案大å°ï¼š{0} mb" + +#: mediagoblin/submit/forms.py:34 msgid "File" msgstr "檔案" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/forms.py:41 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n" +" Markdown</a> for formatting." +msgstr "您å¯ä»¥ä½¿ç”¨\n<a href=\"http://markdown.tw\">\nMarkdown</a> 來排版。" + +#: mediagoblin/submit/views.py:55 msgid "You must provide a file." msgstr "æ‚¨å¿…é ˆæä¾›ä¸€å€‹æª”案" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:69 msgid "Woohoo! Submitted!" msgstr "啊哈ï¼PO 上去啦ï¼" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:138 #, python-format msgid "Collection \"%s\" added!" msgstr "è’è—「%sã€æ–°å¢žå®Œæˆï¼" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/banned.html:20 +msgid "You are Banned." +msgstr "您被å°éŽ–äº†ã€‚" + +#: mediagoblin/templates/mediagoblin/banned.html:24 +#: mediagoblin/templates/mediagoblin/error.html:24 +msgid "Image of goblin stressing out" +msgstr "壓力很大的哥布林示æ„圖" + +#: mediagoblin/templates/mediagoblin/banned.html:26 +msgid "You have been banned" +msgstr "您被" + +#: mediagoblin/templates/mediagoblin/banned.html:28 +#, python-format +msgid "until %(until_when)s" +msgstr "å°éŽ–äº†ï¼Œæœƒåœ¨ %(until_when)s 解除" + +#: mediagoblin/templates/mediagoblin/banned.html:30 +msgid "indefinitely" +msgstr "永久å°éŽ–äº†" + +#: mediagoblin/templates/mediagoblin/base.html:81 msgid "Verify your email!" msgstr "ç¢ºèªæ‚¨çš„é›»å郵件" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:88 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "log out" msgstr "登出" -#: mediagoblin/templates/mediagoblin/base.html:70 -#: mediagoblin/templates/mediagoblin/auth/login.html:28 -#: mediagoblin/templates/mediagoblin/auth/login.html:36 -#: mediagoblin/templates/mediagoblin/auth/login.html:54 -msgid "Log in" -msgstr "登入" - -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:115 #, python-format msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account" msgstr "<a href=\"%(user_url)s\">%(user_name)s</a> 的帳號" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:122 msgid "Change account settings" msgstr "更改帳號è¨å®š" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 -#: mediagoblin/templates/mediagoblin/admin/panel.html:21 -#: mediagoblin/templates/mediagoblin/admin/panel.html:26 +#: mediagoblin/templates/mediagoblin/base.html:126 +#: mediagoblin/templates/mediagoblin/base.html:147 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:27 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26 msgid "Media processing panel" msgstr "媒體處ç†é¢æ¿" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:135 msgid "Log out" -msgstr "" +msgstr "登出" -#: mediagoblin/templates/mediagoblin/base.html:96 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:156 +#: mediagoblin/templates/mediagoblin/base.html:138 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:112 msgid "Add media" msgstr "新增媒體" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:141 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "新增新的è’è—" -#: mediagoblin/templates/mediagoblin/base.html:122 +#: mediagoblin/templates/mediagoblin/base.html:151 +msgid "User management panel" +msgstr "使用者管ç†é¢æ¿" + +#: mediagoblin/templates/mediagoblin/base.html:155 +msgid "Report management panel" +msgstr "å›žå ±ç®¡ç†é¢æ¿" + +#: mediagoblin/templates/mediagoblin/root.html:32 +msgid "Most recent media" +msgstr "最新的媒體" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:21 +msgid "Authorization" +msgstr "èªè¨¼" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:26 +#: mediagoblin/templates/mediagoblin/api/authorize.html:53 +msgid "Authorize" +msgstr "èªè¨¼" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:29 +msgid "You are logged in as" +msgstr "您已經登入為" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:33 +msgid "Do you want to authorize " +msgstr "æ‚¨åŒæ„" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:37 +msgid "an unknown application" +msgstr "一個未知的應用程å¼" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:39 +msgid " to access your account? " +msgstr "å˜å–您的帳號嗎?" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:41 +msgid "Applications with access to your account can: " +msgstr "該程å¼å°‡å¯é€éŽæ‚¨çš„帳號進行以下動作:" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:43 +msgid "Post new media as you" +msgstr "以您的å義張貼新媒體" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:44 +msgid "See your information (e.g profile, media, etc...)" +msgstr "檢視您的資訊 (如個人資料ã€åª’體…ç‰)" + +#: mediagoblin/templates/mediagoblin/api/authorize.html:45 +msgid "Change your information" +msgstr "變更您的個人資料" + +#: mediagoblin/templates/mediagoblin/api/oob.html:21 +msgid "Authorization Finished" +msgstr "èªè¨¼å®Œæˆ" + +#: mediagoblin/templates/mediagoblin/api/oob.html:26 +msgid "Authorization Complete" +msgstr "èªè¨¼å®Œæˆ" + +#: mediagoblin/templates/mediagoblin/api/oob.html:28 +msgid "Copy and paste this into your client:" +msgstr "請將以下文å—複製並貼到應用程å¼ä¸Šï¼š" + +#: mediagoblin/templates/mediagoblin/auth/register.html:28 +#: mediagoblin/templates/mediagoblin/auth/register.html:36 +msgid "Create an account!" +msgstr "建立一個帳號ï¼" + +#: mediagoblin/templates/mediagoblin/auth/register.html:41 +msgid "Create" +msgstr "建立" + +#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 +#, python-format +msgid "" +"Hi %(username)s,\n" +"\n" +"to activate your GNU MediaGoblin account, open the following URL in\n" +"your web browser:\n" +"\n" +"%(verification_url)s" +msgstr "%(username)s 您好:\n\nè¦å•Ÿå‹• GNU MediaGoblin 帳號,請在您的ç€è¦½å™¨ä¸æ‰“開下é¢çš„ç¶²å€ï¼š\n\n%(verification_url)s" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 #, python-format msgid "" "Powered by <a href=\"http://mediagoblin.org/\" title='Version " "%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project." -msgstr "" +msgstr "本站使用 <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>,這是一個 <a href=\"http://gnu.org/\">GNU</a> 專案。" -#: mediagoblin/templates/mediagoblin/base.html:125 +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 #, python-format msgid "" "Released under the <a " @@ -449,147 +922,46 @@ msgid "" "href=\"%(source_link)s\">Source code</a> available." msgstr "以 <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a> 授權釋出。備有<a href=\"%(source_link)s\">原始碼</a>。" -#: mediagoblin/templates/mediagoblin/error.html:24 -msgid "Image of goblin stressing out" -msgstr "滿臉å•號的哥布林" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:30 +msgid "Terms of Service" +msgstr "ä½¿ç”¨è€…æ¢æ¬¾" -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 msgid "Explore" msgstr "探索" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:23 msgid "Hi there, welcome to this MediaGoblin site!" msgstr "å˜¿ï¼æ¡è¿Žä¾†åˆ° MediaGoblin ç«™å°ï¼ " -#: mediagoblin/templates/mediagoblin/root.html:35 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 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> — 與眾ä¸åŒçš„媒體分享網站。" +msgstr "本站使用 <a href=\"http://mediagoblin.org\">MediaGoblin</a> — 超讚的媒體分享架站軟體。" -#: mediagoblin/templates/mediagoblin/root.html:36 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:26 msgid "" "To add your own media, place comments, and more, you can log in with your " "MediaGoblin account." msgstr "您å¯ä»¥ç™»å…¥æ‚¨çš„ MediaGoblin 帳號以進行上傳媒體ã€å¼µè²¼è©•è«–ç‰ç‰ã€‚" -#: mediagoblin/templates/mediagoblin/root.html:38 +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 msgid "Don't have one yet? It's easy!" msgstr "沒有帳號嗎?開帳號很簡單ï¼" -#: mediagoblin/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" -" 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:47 -msgid "Most recent media" -msgstr "最新的媒體" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:29 -msgid "" -"Here you can track the state of media being processed on this instance." -msgstr "æ¤è™•您å¯ä»¥è¿½è¹¤æœ¬ç«™å°è™•ç†åª’體的狀態。" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:32 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 -msgid "Media in-processing" -msgstr "媒體處ç†ä¸" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:58 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 -msgid "No media in-processing" -msgstr "沒有æ£åœ¨è™•ç†ä¸çš„媒體" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:61 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 -msgid "These uploads failed to process:" -msgstr "無法處ç†é€™äº›ä¸Šå‚³å…§å®¹ï¼š" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 -msgid "No failed entries!" -msgstr "沒有失敗的紀錄ï¼" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:92 -msgid "Last 10 successful uploads" -msgstr "最近 10 次æˆåŠŸä¸Šå‚³çš„ç´€éŒ„" - -#: mediagoblin/templates/mediagoblin/admin/panel.html:112 -#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 -msgid "No processed entries, yet!" -msgstr "ç¾åœ¨é‚„沒有處ç†çš„紀錄ï¼" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 -msgid "Set your new password" -msgstr "è¨å®šæ‚¨çš„æ–°å¯†ç¢¼" - -#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 -msgid "Set password" -msgstr "è¨å®šæ–°å¯†ç¢¼" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 -msgid "Recover password" -msgstr "找回密碼" - -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 -msgid "Send instructions" -msgstr "é€å‡ºæŒ‡ç¤º" - -#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:35 msgid "" -"Hi %(username)s,\n" -"\n" -"to change your GNU MediaGoblin password, open the following URL in \n" -"your web browser:\n" -"\n" -"%(verification_url)s\n" "\n" -"If you think this is an error, just ignore this email and continue being\n" -"a happy goblin!" -msgstr "%(username)s 您好:\n\nè¦ä¿®æ”¹ GNU MediaGoblin 的密碼,請在您的ç€è¦½å™¨ä¸æ‰“開下é¢çš„ç¶²å€ï¼š\n\n%(verification_url)s\n\n如果您èªç‚ºé€™å€‹æ˜¯å€‹èª¤æœƒï¼Œè«‹å¿½ç•¥æ¤å°ä¿¡ä»¶ï¼Œç¹¼çºŒç•¶å€‹å¿«æ¨‚的哥布林ï¼" - -#: mediagoblin/templates/mediagoblin/auth/login.html:39 -msgid "Logging in failed!" -msgstr "登入失敗ï¼" - -#: mediagoblin/templates/mediagoblin/auth/login.html:44 -msgid "Don't have an account yet?" -msgstr "還沒有帳號嗎?" - -#: mediagoblin/templates/mediagoblin/auth/login.html:45 -msgid "Create one here!" -msgstr "在這裡建立一個å§ï¼" - -#: mediagoblin/templates/mediagoblin/auth/login.html:51 -msgid "Forgot your password?" -msgstr "忘了密碼嗎?" - -#: mediagoblin/templates/mediagoblin/auth/register.html:28 -#: mediagoblin/templates/mediagoblin/auth/register.html:36 -msgid "Create an account!" -msgstr "建立一個帳號ï¼" +" >Create an account at this site</a>\n" +" or" +msgstr "\n >在本站建立一個帳號</a>\n 或" -#: mediagoblin/templates/mediagoblin/auth/register.html:40 -msgid "Create" -msgstr "建立" - -#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 -#, python-format +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:41 msgid "" -"Hi %(username)s,\n" "\n" -"to activate your GNU MediaGoblin account, open the following URL in\n" -"your web browser:\n" -"\n" -"%(verification_url)s" -msgstr "%(username)s 您好:\n\nè¦å•Ÿå‹• GNU MediaGoblin 帳號,請在您的ç€è¦½å™¨ä¸æ‰“開下é¢çš„ç¶²å€:\n\n%(verification_url)s" +" <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">Set up MediaGoblin on your own server</a>" +msgstr "\n <a class=\"button_action\" href=\"http://mediagoblin.readthedocs.org/\">在您自己的伺æœå™¨ä¸Šå®‰è£ MediaGoblin</a>" #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 @@ -603,13 +975,13 @@ msgid "Editing attachments for %(media_title)s" msgstr "編輯 %(media_title)s 的附件" #: mediagoblin/templates/mediagoblin/edit/attachments.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:159 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:175 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:191 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:207 msgid "Attachments" msgstr "附件" #: mediagoblin/templates/mediagoblin/edit/attachments.html:57 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:181 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:213 msgid "Add attachment" msgstr "新增附件" @@ -626,23 +998,29 @@ msgstr "å–æ¶ˆ" #: mediagoblin/templates/mediagoblin/edit/attachments.html:63 #: mediagoblin/templates/mediagoblin/edit/edit.html:42 -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47 #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33 #: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40 msgid "Save changes" msgstr "儲å˜è®Šæ›´" +#: mediagoblin/templates/mediagoblin/edit/change_email.html:23 +#: mediagoblin/templates/mediagoblin/edit/change_email.html:33 +#, python-format +msgid "Changing %(username)s's email" +msgstr "更改 %(username)s çš„ email ä½å€" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" -msgstr "" +msgstr "真的è¦åˆªé™¤ä½¿ç”¨è€…「%(user_name)sã€ä»¥åŠæ‰€æœ‰ç›¸é—œçš„媒體與評論?" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:35 msgid "Yes, really delete my account" -msgstr "" +msgstr "æ˜¯çš„ï¼Œæˆ‘çœŸçš„è¦æŠŠæˆ‘çš„å¸³è™Ÿåˆªé™¤" #: mediagoblin/templates/mediagoblin/edit/delete_account.html:44 -#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 msgid "Delete permanently" msgstr "永久刪除" @@ -659,9 +1037,13 @@ msgstr "編輯 %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "æ£åœ¨æ”¹è®Š %(username)s 的帳號è¨å®š" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:54 msgid "Delete my account" -msgstr "" +msgstr "刪除我的帳號" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +msgid "Email" +msgstr "Email" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format @@ -674,18 +1056,51 @@ msgstr "編輯 %(collection_title)s" msgid "Editing %(username)s's profile" msgstr "編輯 %(username)s 的個人檔案" +#: mediagoblin/templates/mediagoblin/edit/verification.txt:19 +#, python-format +msgid "" +"Hi,\n" +"\n" +"We wanted to verify that you are %(username)s. If this is the case, then \n" +"please follow the link below to verify your new email address.\n" +"\n" +"%(verification_url)s\n" +"\n" +"If you are not %(username)s or didn't request an email change, you can ignore\n" +"this email." +msgstr "您好:\n\n我們è¦ç¢ºèªæ‚¨æ˜¯ %(username)s 。如果確實如æ¤ï¼Œè«‹é»žé¸ä»¥ä¸‹é€£çµä¾†èªè¨¼æ‚¨çš„æ–° email ä½å€ã€‚\n\n%(verification_url)s\n\nå¦‚æžœæ‚¨ä¸æ˜¯ %(username)s æˆ–æ²’æœ‰è¦æ±‚修改 email ä½å€ï¼Œè«‹å¿½ç•¥é€™å°éƒµä»¶ã€‚" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:4 +msgid "New comments" +msgstr "新的評論" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:24 +#: mediagoblin/templates/mediagoblin/media_displays/image.html:39 +#: mediagoblin/templates/mediagoblin/moderation/report.html:55 +#: mediagoblin/templates/mediagoblin/moderation/report.html:117 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:139 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:168 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:48 +#, python-format +msgid "%(formatted_time)s ago" +msgstr "%(formatted_time)s å‰" + +#: mediagoblin/templates/mediagoblin/fragments/header_notifications.html:41 +msgid "Mark all read" +msgstr "全部標示為已讀" + #: mediagoblin/templates/mediagoblin/listings/collection.html:30 #: mediagoblin/templates/mediagoblin/listings/collection.html:35 #: mediagoblin/templates/mediagoblin/listings/tag.html:30 #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "æ¤åª’體被 tag æˆï¼š%(tag_name)s" +msgstr "這個媒體具有以下標籤:%(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:55 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:67 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:74 msgid "Download" msgstr "下載" @@ -708,7 +1123,8 @@ msgid "" msgstr "您å¯ä»¥åœ¨ <a href=\"http://getfirefox.com\">http://getfirefox.com</a> å–å¾—å¯ä»¥æ’放æ¤è²éŸ³çš„ç€è¦½å™¨ï¼" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 -#: mediagoblin/templates/mediagoblin/media_displays/video.html:61 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:73 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:80 msgid "Original file" msgstr "原始檔案" @@ -716,6 +1132,11 @@ msgstr "原始檔案" msgid "WebM file (Vorbis codec)" msgstr "WebM 檔案 (Vorbis 編碼)" +#: mediagoblin/templates/mediagoblin/media_displays/image.html:36 +msgid "Created" +msgstr "建立於" + +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:87 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:93 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:99 @@ -726,70 +1147,267 @@ msgstr "WebM 檔案 (Vorbis 編碼)" msgid "Image for %(media_title)s" msgstr " %(media_title)s 的照片" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 -msgid "Toggle Rotate" -msgstr "åˆ‡æ›æ—‹è½‰" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:81 +msgid "PDF file" +msgstr "PDF 檔" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Perspective" -msgstr "視角" +msgstr "é€è¦–" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:115 msgid "Front" msgstr "æ£é¢" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:118 msgid "Top" msgstr "é ‚é¢" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Side" msgstr "å´é¢" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:126 msgid "WebGL" msgstr "WebGL" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:132 msgid "Download model" msgstr "下載模型" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:140 msgid "File Format" msgstr "æª”æ¡ˆæ ¼å¼" -#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 +#: mediagoblin/templates/mediagoblin/media_displays/stl.html:142 msgid "Object Height" msgstr "物件高度" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:44 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:63 msgid "" "Sorry, this video will not work because\n" " your web browser does not support HTML5 \n" " video." -msgstr "" +msgstr "抱æ‰ï¼Œç”±æ–¼æ‚¨çš„ç€è¦½å™¨ä¸æ”¯æ´ HTML5 å½±ç‰‡ï¼Œæœ¬å½±ç‰‡ç„¡æ³•æ’æ”¾" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:47 +#: mediagoblin/templates/mediagoblin/media_displays/video.html:66 msgid "" "You can get a modern web browser that \n" " can play this video at <a href=\"http://getfirefox.com\">\n" " http://getfirefox.com</a>!" -msgstr "" +msgstr "您å¯ä»¥åœ¨ <a href=\"http://getfirefox.com\">http://getfirefox.com</a> å–å¾—å¯ä»¥æ’放æ¤å½±ç‰‡çš„先進ç€è¦½å™¨ã€‚" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:88 +msgid "WebM file (VP8/Vorbis)" +msgstr "WebM 檔案 (VP8/Vorbis)" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:30 +msgid "" +"Here you can track the state of media being processed on this instance." +msgstr "æ¤è™•您å¯ä»¥è¿½è¹¤æœ¬ç«™å°è™•ç†åª’體的狀態。" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 +msgid "Media in-processing" +msgstr "媒體處ç†ä¸" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56 +msgid "No media in-processing" +msgstr "沒有æ£åœ¨è™•ç†ä¸çš„媒體" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59 +msgid "These uploads failed to process:" +msgstr "無法處ç†é€™äº›ä¸Šå‚³å…§å®¹ï¼š" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:91 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 +msgid "No failed entries!" +msgstr "沒有失敗的紀錄ï¼" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:93 +msgid "Last 10 successful uploads" +msgstr "最近 10 次æˆåŠŸä¸Šå‚³çš„ç´€éŒ„" + +#: mediagoblin/templates/mediagoblin/moderation/media_panel.html:113 +#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 +msgid "No processed entries, yet!" +msgstr "ç¾åœ¨é‚„沒有處ç†çš„紀錄ï¼" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:27 +msgid "Sorry, no such report found." +msgstr "抱æ‰ï¼Œæ‰¾ä¸åˆ°è©²å›žå ±ã€‚" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:32 +msgid "Return to Reports Panel" +msgstr "å›žåˆ°å›žå ±é¢æ¿" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:33 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:155 +msgid "Report" +msgstr "å›žå ±" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:36 +msgid "Reported comment" +msgstr "å·²ç¶“å›žå ±çš„è©•è«–" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:81 +#, python-format +msgid "" +"\n" +" â– Reported media by <a href=\"%(user_url)s\">%(user_name)s</a>\n" +" " +msgstr "\n â– è©²åª’é«”çš„å›žå ±ä¾†è‡ª <a href=\"%(user_url)s\">%(user_name)s</a>\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:90 +#, python-format +msgid "" +"\n" +" CONTENT BY\n" +" <a href=\"%(user_url)s\"> %(user_name)s</a>\n" +" HAS BEEN DELETED\n" +" " +msgstr "\n <a href=\"%(user_url)s\"> %(user_name)s</a>\n 的內容已被刪除\n " + +#: mediagoblin/templates/mediagoblin/moderation/report.html:130 +msgid "Resolve" +msgstr "處ç†" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:134 +#: mediagoblin/templates/mediagoblin/moderation/report.html:153 +msgid "Resolve This Report" +msgstr "處ç†é€™é …å›žå ±" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:145 +msgid "Status" +msgstr "狀態" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:147 +msgid "RESOLVED" +msgstr "已經處ç†" + +#: mediagoblin/templates/mediagoblin/moderation/report.html:155 +msgid "You cannot take action against an administrator" +msgstr "您ä¸èƒ½å°ç®¡ç†è€…進行æ“作" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:22 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:27 +msgid "Report panel" +msgstr "å›žå ±é¢æ¿" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:30 +msgid "" +"\n" +" Here you can look up open reports that have been filed by users.\n" +" " +msgstr "\n 在這裡您å¯ä»¥çœ‹åˆ°å°šæœªè™•ç†çš„ä½¿ç”¨è€…å›žå ±\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:35 +msgid "Active Reports Filed" +msgstr "å·²é€å‡ºçš„ç¾è¡Œå›žå ±" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:77 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:171 +msgid "Offender" +msgstr "被告" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:78 +msgid "When Reported" +msgstr "å›žå ±æ™‚é–“" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:79 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:173 +msgid "Reported By" +msgstr "原告" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:80 +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:174 +msgid "Reason" +msgstr "ç†ç”±" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:94 +#, python-format +msgid "" +"\n" +" Comment Report #%(report_id)s\n" +" " +msgstr "\nè©•è«–å›žå ± #%(report_id)s" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:109 +#, python-format +msgid "" +"\n" +" Media Report #%(report_id)s\n" +" " +msgstr "\nåª’é«”å›žå ± #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:123 +msgid "No open reports found." +msgstr "沒有尚未處ç†çš„å›žå ±ã€‚" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:125 +msgid "Closed Reports" +msgstr "å·²çµæ¡ˆçš„å›žå ±" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:170 +msgid "Resolved" +msgstr "已處ç†" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:172 +msgid "Action Taken" +msgstr "發生時間" + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:185 +#, python-format +msgid "" +"\n" +" Closed Report #%(report_id)s\n" +" " +msgstr "\nå·²çµæ¡ˆå›žå ± #%(report_id)s\n " + +#: mediagoblin/templates/mediagoblin/moderation/report_panel.html:199 +msgid "No closed reports found." +msgstr "找ä¸åˆ°å·²çµæ¡ˆçš„å›žå ±ã€‚" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:21 +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:26 +msgid "User panel" +msgstr "ä½¿ç”¨è€…é¢æ¿" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:29 +msgid "" +"\n" +" Here you can look up users in order to take punitive actions on them.\n" +" " +msgstr "\n在這裡您å¯ä»¥æŸ¥è©¢ä½¿ç”¨è€…,以進行å„é …è™•ç½®ã€‚ " + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:34 +msgid "Active Users" +msgstr "活動ä¸çš„使用者" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:75 +msgid "ID" +msgstr "ID" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:77 +msgid "When Joined" +msgstr "åŠ å…¥æ™‚é–“" -#: mediagoblin/templates/mediagoblin/media_displays/video.html:69 -msgid "WebM file (640p; VP8/Vorbis)" -msgstr "WebM 檔案 (640p; VP8/Vorbis)" +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:78 +msgid "# of Comments Posted" +msgstr "張貼評論數" + +#: mediagoblin/templates/mediagoblin/moderation/user_panel.html:95 +msgid "No users found." +msgstr "找ä¸åˆ°è©²ä½¿ç”¨è€…。" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" msgstr "新增è’è—" -#: mediagoblin/templates/mediagoblin/submit/start.html:23 -#: mediagoblin/templates/mediagoblin/submit/start.html:30 +#: mediagoblin/templates/mediagoblin/submit/start.html:28 +#: mediagoblin/templates/mediagoblin/submit/start.html:35 msgid "Add your media" msgstr "åŠ å…¥æ‚¨çš„åª’é«”" @@ -808,11 +1426,6 @@ msgstr "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>" msgid "Edit" msgstr "編輯" -#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56 -#: mediagoblin/templates/mediagoblin/user_pages/media.html:83 -msgid "Delete" -msgstr "刪除" - #: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -824,19 +1437,19 @@ msgstr "真的è¦åˆªé™¤ %(title)s?" msgid "Really remove %(media_title)s from %(collection_title)s?" msgstr "確定è¦å¾ž %(collection_title)s 移除 %(media_title)s 嗎?" -#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54 msgid "Remove" msgstr "移除" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21 #, python-format msgid "%(username)s's collections" -msgstr "" +msgstr "%(username)s çš„è’è—" #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections" -msgstr "" +msgstr "<a href=\"%(user_url)s\">%(username)s</a> çš„è’è—" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -855,7 +1468,7 @@ msgstr "%(username)s的媒體" msgid "" "<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a " "href=\"%(tag_url)s\">%(tag)s</a>" -msgstr "" +msgstr "標籤為 <a href=\"%(tag_url)s\">%(tag)s</a> çš„ <a href=\"%(user_url)s\">%(username)s</a> 的媒體" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -867,30 +1480,27 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a> 的媒體" msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>" msgstr "â– ç€è¦½ <a href=\"%(user_url)s\">%(username)s</a> 的媒體" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:97 msgid "Add a comment" msgstr "新增評論" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:108 msgid "Add this comment" msgstr "å¢žåŠ è©•è«–" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "在" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:112 +msgid "Comment Preview" +msgstr "è©•è«–é 覽" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"<h3>Added on</h3>\n" -" <p>%(date)s</p>" -msgstr "<h3>åŠ å…¥æ—¥æœŸ</h3>\n <p>%(date)s</p>" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:166 +msgid "Added" +msgstr "新增於" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 #, python-format msgid "Add “%(media_title)s†to a collection" -msgstr "" +msgstr "åŠ å…¥ “%(media_title)s†至è’è—" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" @@ -909,96 +1519,118 @@ msgstr "您å¯ä»¥åœ¨é€™è£¡è¿½è¹¤æ‚¨çš„è—廊ä¸åª’體處ç†çš„狀態。" msgid "Your last 10 successful uploads" msgstr "您的最近 10 次æˆåŠŸä¸Šå‚³çš„ç´€éŒ„" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#: mediagoblin/templates/mediagoblin/user_pages/report.html:21 +msgid "<h2>File a Report</h2>" +msgstr "<h2>寄é€å›žå ±</h2>" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:24 +msgid "Reporting this Comment" +msgstr "å›žå ±è©²è©•è«–" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:60 +msgid "Reporting this Media Entry" +msgstr "å›žå ±è©²åª’é«”é …ç›®" + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:72 +#, python-format +msgid "" +"\n" +" â– Published by <a href=\"%(user_url)s\"\n" +" class=\"comment_authorlink\">%(username)s</a>\n" +" " +msgstr "\nâ– ç”± <a href=\"%(user_url)s\"\nclass=\"comment_authorlink\">%(username)s</a> 發佈\n " + +#: mediagoblin/templates/mediagoblin/user_pages/report.html:81 +msgid "File Report " +msgstr "é€å‡ºå›žå ±" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:34 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:45 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:25 #, python-format msgid "%(username)s's profile" msgstr "%(username)s 的個人檔案" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 -msgid "Sorry, no such user found." -msgstr "抱æ‰ï¼Œæ‰¾ä¸åˆ°é€™å€‹ä½¿ç”¨è€…。" +#: mediagoblin/templates/mediagoblin/user_pages/user.html:52 +msgid "Here's a spot to tell others about yourself." +msgstr "這個地方能讓您å‘他人介紹自己。" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:56 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +msgid "Edit profile" +msgstr "編輯個人檔案" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:61 +msgid "This user hasn't filled in their profile (yet)." +msgstr "這個使用者(é‚„)沒有填寫個人檔案。" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:80 +msgid "Browse collections" +msgstr "ç€è¦½è’è—" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:93 +#, python-format +msgid "View all of %(username)s's media" +msgstr "查看 %(username)s 的全部媒體" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:106 +msgid "" +"This is where your media will appear, but you don't seem to have added " +"anything yet." +msgstr "æ¤è™•是您的媒體會出ç¾çš„åœ°æ–¹ï¼Œä½†æ˜¯ä¼¼ä¹Žé‚„æ²’æœ‰åŠ å…¥ä»»ä½•æ±è¥¿ã€‚" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:118 +#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 +#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 +msgid "There doesn't seem to be any media here yet..." +msgstr "那裡好åƒé‚„沒有任何的媒體…" + +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:40 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:60 msgid "Email verification needed" msgstr "需è¦èªè‰é›»å郵件" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:43 msgid "Almost done! Your account still needs to be activated." msgstr "快完æˆäº†ï¼ä½†æ‚¨éœ€è¦å•Ÿç”¨æ‚¨çš„帳號。" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:48 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "啟用æ¥é©Ÿçš„ email 將會寄到您的信箱。" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:52 msgid "In case it doesn't:" msgstr "如果ä»ç„¶ç„¡æ³•èªè‰ï¼Œæ‚¨å¯ä»¥ï¼š" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:55 msgid "Resend verification email" msgstr "é‡é€èªè‰ä¿¡" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:63 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "有人用了這個帳號登錄了,但是這個帳號需è¦è¢«å•Ÿç”¨ã€‚" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 +#: mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html:68 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." msgstr "如果您就是本人但是掉了èªè‰ä¿¡ï¼Œæ‚¨å¯ä»¥ <a href=\"%(login_url)s\">登入</a> 然後é‡é€ä¸€æ¬¡ã€‚" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 -msgid "Here's a spot to tell others about yourself." -msgstr "這個地方能讓您å‘他人介紹自己。" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:100 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:117 -msgid "Edit profile" -msgstr "編輯個人檔案" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:105 -msgid "This user hasn't filled in their profile (yet)." -msgstr "這個使用者(é‚„)沒有填寫個人檔案。" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:124 -msgid "Browse collections" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:137 -#, python-format -msgid "View all of %(username)s's media" -msgstr "查看 %(username)s 的全部媒體" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:150 -msgid "" -"This is where your media will appear, but you don't seem to have added " -"anything yet." -msgstr "æ¤è™•是您的媒體會出ç¾çš„åœ°æ–¹ï¼Œä½†æ˜¯ä¼¼ä¹Žé‚„æ²’æœ‰åŠ å…¥ä»»ä½•æ±è¥¿ã€‚" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:162 -#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84 -#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70 -msgid "There doesn't seem to be any media here yet..." -msgstr "那裡好åƒé‚„沒有任何的媒體…" - #: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49 msgid "(remove)" msgstr " (移除)" #: mediagoblin/templates/mediagoblin/utils/collections.html:21 msgid "Collected in" -msgstr "" +msgstr "è’集了" #: mediagoblin/templates/mediagoblin/utils/collections.html:40 msgid "Add to a collection" -msgstr "" +msgstr "åŠ å…¥è‡³è’è—" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 #: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21 @@ -1036,50 +1668,85 @@ msgstr "æ›´æ–°çš„" msgid "older" msgstr "更舊的" +#: mediagoblin/templates/mediagoblin/utils/report.html:25 +msgid "Report media" +msgstr "å›žå ±åª’é«”" + #: mediagoblin/templates/mediagoblin/utils/tags.html:20 msgid "Tagged with" msgstr "標籤" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "無法讀å–圖片檔案。" -#: mediagoblin/tools/response.py:35 +#: mediagoblin/tools/response.py:38 msgid "Oops!" msgstr "糟糕ï¼" -#: mediagoblin/tools/response.py:36 +#: mediagoblin/tools/response.py:39 msgid "An error occured" msgstr "發生錯誤" -#: mediagoblin/tools/response.py:51 +#: mediagoblin/tools/response.py:53 +msgid "Bad Request" +msgstr "錯誤的請求" + +#: mediagoblin/tools/response.py:55 +msgid "The request sent to the server is invalid, please double check it" +msgstr "傳é€åˆ°æ¤ä¼ºæœå™¨çš„請求無效,請å†ä¸‰ç¢ºèª" + +#: mediagoblin/tools/response.py:63 msgid "Operation not allowed" msgstr "æ“作ä¸å…許" -#: mediagoblin/tools/response.py:52 +#: mediagoblin/tools/response.py:64 msgid "" "Sorry Dave, I can't let you do that!</p><p>You have tried to perform a " "function that you are not allowed to. Have you been trying to delete all " "user accounts again?" msgstr "Dave å°ä¸èµ·ï¼Œæˆ‘ä¸èƒ½è®“ä½ é€™æ¨£åšï¼</p><p>您æ£åœ¨è©¦è‘—æ“作ä¸å…許您使用的功能。您打算刪除所有使用者的帳號嗎?" -#: mediagoblin/tools/response.py:60 +#: mediagoblin/tools/response.py:72 msgid "" "There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." msgstr "ä¸å¥½æ„æ€ï¼Œçœ‹èµ·ä¾†é€™å€‹ç¶²å€ä¸Šæ²’有網é 。</p><p>å¦‚æžœæ‚¨ç¢ºå®šé€™å€‹ç¶²å€æ˜¯æ£ç¢ºçš„,您在尋找的é é¢å¯èƒ½å·²ç¶“移動或是被刪除了。" +#: mediagoblin/tools/timesince.py:62 +msgid "year" +msgstr "å¹´" + +#: mediagoblin/tools/timesince.py:63 +msgid "month" +msgstr "月" + +#: mediagoblin/tools/timesince.py:64 +msgid "week" +msgstr "週" + +#: mediagoblin/tools/timesince.py:65 +msgid "day" +msgstr "æ—¥" + +#: mediagoblin/tools/timesince.py:66 +msgid "hour" +msgstr "å°æ™‚" + +#: mediagoblin/tools/timesince.py:67 +msgid "minute" +msgstr "分" + #: mediagoblin/user_pages/forms.py:23 msgid "Comment" -msgstr "" +msgstr "è©•è«–" #: mediagoblin/user_pages/forms.py:25 msgid "" -"You can use <a " -"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for" -" formatting." -msgstr "您å¯ä»¥ç”¨ <a href=\"http://markdown.tw\">Markdown</a> 來排版。" +"You can use <a href=\"http://daringfireball.net/projects/markdown/basics\" " +"target=\"_blank\">Markdown</a> for formatting." +msgstr "您å¯ä»¥ä½¿ç”¨ <a href=\"http://markdown.tw\" target=\"_blank\">Markdown</a> 來排版。" #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1091,7 +1758,7 @@ msgstr "我確定我è¦å¾žè’è—ä¸ç§»é™¤æ¤é …ç›®" #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "è’è—" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" @@ -1101,73 +1768,84 @@ msgstr "— è«‹é¸æ“‡ —" msgid "Include a note" msgstr "åŠ è¨»" -#: mediagoblin/user_pages/lib.py:56 -msgid "commented on your post" -msgstr "在您的內容張貼評論" +#: mediagoblin/user_pages/forms.py:49 +msgid "" +"You can use\n" +" <a href=\"http://daringfireball.net/projects/markdown/basics\" target=\"_blank\">\n" +" Markdown</a> for formatting." +msgstr "您å¯ä»¥ä½¿ç”¨\n<a href=\"http://markdown.tw\" target=\"_blank\">\nMarkdown</a> 來排版。" + +#: mediagoblin/user_pages/forms.py:55 mediagoblin/user_pages/forms.py:61 +msgid "Reason for Reporting" +msgstr "å›žå ±ç†ç”±" + +#: mediagoblin/user_pages/views.py:178 +msgid "Sorry, comments are disabled." +msgstr "抱æ‰ï¼Œè©•論被關閉了。" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:183 msgid "Oops, your comment was empty." -msgstr "啊,您的留言是空的。" +msgstr "啊,您的評論是空的。" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:189 msgid "Your comment has been posted!" -msgstr "您的留言已經張貼完æˆï¼" +msgstr "您的評論已經張貼完æˆï¼" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:225 msgid "Please check your entries and try again." msgstr "è«‹æª¢æŸ¥é …ç›®ä¸¦é‡è©¦ã€‚" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:265 msgid "You have to select or add a collection" msgstr "您需è¦é¸æ“‡æˆ–是新增一個è’è—" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:276 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "「%sã€å·²ç¶“在「%sã€è’è—" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:282 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "「%sã€åŠ å…¥ã€Œ%sã€è’è—" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:307 msgid "You deleted the media." msgstr "您已經刪除æ¤åª’體。" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:319 msgid "The media was not deleted because you didn't check that you were sure." msgstr "由於您沒有勾é¸ç¢ºèªï¼Œè©²åª’體沒有被移除。" -#: mediagoblin/user_pages/views.py:301 +#: mediagoblin/user_pages/views.py:326 msgid "You are about to delete another user's media. Proceed with caution." msgstr "您æ£åœ¨åˆªé™¤åˆ¥äººçš„媒體,請å°å¿ƒæ“作。" -#: mediagoblin/user_pages/views.py:375 +#: mediagoblin/user_pages/views.py:399 msgid "You deleted the item from the collection." msgstr "您已經從該è’è—ä¸åˆªé™¤è©²é …目。" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:403 msgid "The item was not removed because you didn't check that you were sure." msgstr "由於您沒有勾é¸ç¢ºèªï¼Œè©²é …目沒有被移除。" -#: mediagoblin/user_pages/views.py:389 +#: mediagoblin/user_pages/views.py:411 msgid "" "You are about to delete an item from another user's collection. Proceed with" " caution." msgstr "您æ£åœ¨å¾žåˆ¥äººçš„è’è—ä¸åˆªé™¤é …目,請å°å¿ƒæ“作。" -#: mediagoblin/user_pages/views.py:422 +#: mediagoblin/user_pages/views.py:443 #, python-format msgid "You deleted the collection \"%s\"" msgstr "您已經刪除「%sã€è’è—。" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:450 msgid "" "The collection was not deleted because you didn't check that you were sure." msgstr "由於您沒有勾é¸ç¢ºèªï¼Œè©²è’è—æ²’有被移除。" -#: mediagoblin/user_pages/views.py:439 +#: mediagoblin/user_pages/views.py:458 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "您æ£åœ¨åˆªé™¤åˆ¥äººçš„è’è—,請å°å¿ƒæ“作。" diff --git a/mediagoblin/init/__init__.py b/mediagoblin/init/__init__.py index d16027db..e0711416 100644 --- a/mediagoblin/init/__init__.py +++ b/mediagoblin/init/__init__.py @@ -24,6 +24,7 @@ from mediagoblin import mg_globals from mediagoblin.mg_globals import setup_globals from mediagoblin.db.open import setup_connection_and_db_from_config, \ check_db_migrations_current, load_models +from mediagoblin.tools.pluginapi import hook_runall from mediagoblin.tools.workbench import WorkbenchManager from mediagoblin.storage import storage_system_from_config @@ -57,16 +58,20 @@ def setup_global_and_app_config(config_path): return global_config, app_config -def setup_database(): +def setup_database(run_migrations=False): app_config = mg_globals.app_config + global_config = mg_globals.global_config # Load all models for media types (plugins, ...) load_models(app_config) - # Set up the database - db = setup_connection_and_db_from_config(app_config) - - check_db_migrations_current(db) + db = setup_connection_and_db_from_config(app_config, run_migrations) + if run_migrations: + #Run the migrations to initialize/update the database. + from mediagoblin.gmg_commands.dbupdate import run_all_migrations + run_all_migrations(db, app_config, global_config) + else: + check_db_migrations_current(db) setup_globals(database=db) @@ -116,6 +121,12 @@ def get_staticdirector(app_config): direct_domains = {None: app_config['direct_remote_path'].strip()} direct_domains['theme'] = app_config['theme_web_path'].strip() + # Let plugins load additional paths + for plugin_static in hook_runall("static_setup"): + direct_domains[plugin_static.name] = "%s/%s" % ( + app_config['plugin_web_path'].rstrip('/'), + plugin_static.name) + return staticdirect.StaticDirect( direct_domains) diff --git a/mediagoblin/init/celery/__init__.py b/mediagoblin/init/celery/__init__.py index 169cc935..57242bf6 100644 --- a/mediagoblin/init/celery/__init__.py +++ b/mediagoblin/init/celery/__init__.py @@ -16,12 +16,18 @@ import os import sys +import logging from celery import Celery from mediagoblin.tools.pluginapi import hook_runall -MANDATORY_CELERY_IMPORTS = ['mediagoblin.processing.task'] +_log = logging.getLogger(__name__) + + +MANDATORY_CELERY_IMPORTS = [ + 'mediagoblin.processing.task', + 'mediagoblin.notifications.task'] DEFAULT_SETTINGS_MODULE = 'mediagoblin.init.celery.dummy_settings_module' @@ -97,3 +103,13 @@ def setup_celery_from_config(app_config, global_config, if set_environ: os.environ['CELERY_CONFIG_MODULE'] = settings_module + + # Replace the default celery.current_app.conf if celery has already been + # initiated + from celery import current_app + + _log.info('Setting celery configuration from object "{0}"'.format( + settings_module)) + current_app.config_from_object(this_module) + + _log.debug('Celery broker host: {0}'.format(current_app.conf['BROKER_HOST'])) diff --git a/mediagoblin/init/config.py b/mediagoblin/init/config.py index ac4ab9bf..11a91cff 100644 --- a/mediagoblin/init/config.py +++ b/mediagoblin/init/config.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import logging import os import pkg_resources @@ -21,6 +22,9 @@ from configobj import ConfigObj, flatten_errors from validate import Validator +_log = logging.getLogger(__name__) + + CONFIG_SPEC_PATH = pkg_resources.resource_filename( 'mediagoblin', 'config_spec.ini') @@ -42,6 +46,9 @@ def read_mediagoblin_config(config_path, config_spec=CONFIG_SPEC_PATH): Also provides %(__file__)s and %(here)s values of this file and its directory respectively similar to paste deploy. + Also reads for [plugins] section, appends all config_spec.ini + files from said plugins into the general config_spec specification. + This function doesn't itself raise any exceptions if validation fails, you'll have to do something @@ -57,10 +64,45 @@ def read_mediagoblin_config(config_path, config_spec=CONFIG_SPEC_PATH): """ config_path = os.path.abspath(config_path) + # PRE-READ of config file. This allows us to fetch the plugins so + # we can add their plugin specs to the general config_spec. + config = ConfigObj( + config_path, + interpolation='ConfigParser') + + plugins = config.get("plugins", {}).keys() + plugin_configs = {} + + for plugin in plugins: + try: + plugin_config_spec_path = pkg_resources.resource_filename( + plugin, "config_spec.ini") + if not os.path.exists(plugin_config_spec_path): + continue + + plugin_config_spec = ConfigObj( + plugin_config_spec_path, + encoding='UTF8', list_values=False, _inspec=True) + _setup_defaults(plugin_config_spec, config_path) + + if not "plugin_spec" in plugin_config_spec: + continue + + plugin_configs[plugin] = plugin_config_spec["plugin_spec"] + + except ImportError: + _log.warning( + "When setting up config section, could not import '%s'" % + plugin) + + # Now load the main config spec config_spec = ConfigObj( config_spec, encoding='UTF8', list_values=False, _inspec=True) + # append the plugin specific sections of the config spec + config_spec['plugins'] = plugin_configs + _setup_defaults(config_spec, config_path) config = ConfigObj( diff --git a/mediagoblin/listings/views.py b/mediagoblin/listings/views.py index 35af7148..07dbb3d5 100644 --- a/mediagoblin/listings/views.py +++ b/mediagoblin/listings/views.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +from mediagoblin import mg_globals from mediagoblin.db.models import MediaEntry from mediagoblin.db.util import media_entries_for_tag_slug from mediagoblin.tools.pagination import Pagination @@ -80,6 +81,17 @@ def atom_feed(request): link = request.urlgen('index', qualified=True) feed_title += "for all recent items" + atomlinks = [ + {'href': link, + 'rel': 'alternate', + 'type': 'text/html'}] + + if mg_globals.app_config["push_urls"]: + for push_url in mg_globals.app_config["push_urls"]: + atomlinks.append({ + 'rel': 'hub', + 'href': push_url}) + cursor = cursor.order_by(MediaEntry.created.desc()) cursor = cursor.limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS) @@ -87,9 +99,8 @@ def atom_feed(request): feed_title, feed_url=request.url, id=link, - links=[{'href': link, - 'rel': 'alternate', - 'type': 'text/html'}]) + links=atomlinks) + for entry in cursor: feed.add(entry.get('title'), entry.description_html, diff --git a/mediagoblin/meddleware/csrf.py b/mediagoblin/meddleware/csrf.py index 661f0ba2..44d42d75 100644 --- a/mediagoblin/meddleware/csrf.py +++ b/mediagoblin/meddleware/csrf.py @@ -111,7 +111,7 @@ class CsrfMeddleware(BaseMeddleware): httponly=True) # update the Vary header - response.vary = (getattr(response, 'vary', None) or []) + ['Cookie'] + response.vary = list(getattr(response, 'vary', None) or []) + ['Cookie'] def _make_token(self, request): """Generate a new token to use for CSRF protection.""" diff --git a/mediagoblin/media_types/__init__.py b/mediagoblin/media_types/__init__.py index 20e1918e..2e392317 100644 --- a/mediagoblin/media_types/__init__.py +++ b/mediagoblin/media_types/__init__.py @@ -15,12 +15,10 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import sys import logging import tempfile -from mediagoblin import mg_globals -from mediagoblin.tools.common import import_component +from mediagoblin.tools.pluginapi import hook_handle from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ _log = logging.getLogger(__name__) @@ -52,86 +50,35 @@ class MediaManagerBase(object): return hasattr(self, i) -class CompatMediaManager(object): - def __init__(self, mm_dict, entry=None): - self.mm_dict = mm_dict - self.entry = entry - - def __call__(self, entry): - "So this object can look like a class too, somehow" - assert self.entry is None - return self.__class__(self.mm_dict, entry) - - def __getitem__(self, i): - return self.mm_dict[i] - - def __contains__(self, i): - return (i in self.mm_dict) - - @property - def media_fetch_order(self): - return self.mm_dict.get('media_fetch_order') - - def sniff_handler(self, *args, **kwargs): - func = self.mm_dict.get("sniff_handler", None) - if func is not None: - return func(*args, **kwargs) - return False - - def __getattr__(self, i): - return self.mm_dict[i] - - -def sniff_media(media): +def sniff_media(media_file, filename): ''' Iterate through the enabled media types and find those suited for a certain file. ''' try: - return get_media_type_and_manager(media.filename) + return get_media_type_and_manager(filename) except FileTypeNotSupported: _log.info('No media handler found by file extension. Doing it the expensive way...') # Create a temporary file for sniffers suchs as GStreamer-based # Audio video - media_file = tempfile.NamedTemporaryFile() - media_file.write(media.stream.read()) - media.stream.seek(0) - - for media_type, manager in get_media_managers(): - _log.info('Sniffing {0}'.format(media_type)) - if manager.sniff_handler(media_file, media=media): - _log.info('{0} accepts the file'.format(media_type)) - return media_type, manager - else: - _log.debug('{0} did not accept the file'.format(media_type)) + tmp_media_file = tempfile.NamedTemporaryFile() + tmp_media_file.write(media_file.read()) + tmp_media_file.seek(0) + media_file.seek(0) + + media_type = hook_handle('sniff_handler', tmp_media_file, filename) + if media_type: + _log.info('{0} accepts the file'.format(media_type)) + return media_type, hook_handle(('media_manager', media_type)) + else: + _log.debug('{0} did not accept the file'.format(media_type)) raise FileTypeNotSupported( # TODO: Provide information on which file types are supported _(u'Sorry, I don\'t support that file type :(')) -def get_media_types(): - """ - Generator, yields the available media types - """ - for media_type in mg_globals.app_config['media_types']: - yield media_type - - -def get_media_managers(): - ''' - Generator, yields all enabled media managers - ''' - for media_type in get_media_types(): - mm = import_component(media_type + ":MEDIA_MANAGER") - - if isinstance(mm, dict): - mm = CompatMediaManager(mm) - - yield media_type, mm - - def get_media_type_and_manager(filename): ''' Try to find the media type based on the file name, extension @@ -142,11 +89,10 @@ def get_media_type_and_manager(filename): # Get the file extension ext = os.path.splitext(filename)[1].lower() - for media_type, manager in get_media_managers(): - # Omit the dot from the extension and match it against - # the media manager - if ext[1:] in manager.accepted_extensions: - return media_type, manager + # Omit the dot from the extension and match it against + # the media manager + if hook_handle('get_media_type_and_manager', ext[1:]): + return hook_handle('get_media_type_and_manager', ext[1:]) else: _log.info('File {0} has no file extension, let\'s hope the sniffers get it.'.format( filename)) diff --git a/mediagoblin/media_types/ascii/__init__.py b/mediagoblin/media_types/ascii/__init__.py index 856d1d7b..1ee44988 100644 --- a/mediagoblin/media_types/ascii/__init__.py +++ b/mediagoblin/media_types/ascii/__init__.py @@ -14,16 +14,28 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from mediagoblin.media_types.ascii.processing import process_ascii, \ +from mediagoblin.media_types import MediaManagerBase +from mediagoblin.media_types.ascii.processing import AsciiProcessingManager, \ sniff_handler +ACCEPTED_EXTENSIONS = ["txt", "asc", "nfo"] +MEDIA_TYPE = 'mediagoblin.media_types.ascii' -MEDIA_MANAGER = { - "human_readable": "ASCII", - "processor": process_ascii, # alternately a string, - # 'mediagoblin.media_types.image.processing'? - "sniff_handler": sniff_handler, - "display_template": "mediagoblin/media_displays/ascii.html", - "default_thumb": "images/media_thumbs/ascii.jpg", - "accepted_extensions": [ - "txt", "asc", "nfo"]} + +class ASCIIMediaManager(MediaManagerBase): + human_readable = "ASCII" + display_template = "mediagoblin/media_displays/ascii.html" + default_thumb = "images/media_thumbs/ascii.jpg" + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, ASCIIMediaManager + + +hooks = { + 'get_media_type_and_manager': get_media_type_and_manager, + ('media_manager', MEDIA_TYPE): lambda: ASCIIMediaManager, + ('reprocess_manager', MEDIA_TYPE): lambda: AsciiProcessingManager, + 'sniff_handler': sniff_handler, +} diff --git a/mediagoblin/media_types/ascii/config_spec.ini b/mediagoblin/media_types/ascii/config_spec.ini new file mode 100644 index 00000000..24b05053 --- /dev/null +++ b/mediagoblin/media_types/ascii/config_spec.ini @@ -0,0 +1,4 @@ +[plugin_spec] +thumbnail_font = string(default=None) + + diff --git a/mediagoblin/media_types/ascii/processing.py b/mediagoblin/media_types/ascii/processing.py index 2f6079be..84030362 100644 --- a/mediagoblin/media_types/ascii/processing.py +++ b/mediagoblin/media_types/ascii/processing.py @@ -13,6 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import argparse import chardet import os try: @@ -22,125 +23,254 @@ except ImportError: import logging from mediagoblin import mg_globals as mgg -from mediagoblin.processing import create_pub_filepath +from mediagoblin.processing import ( + create_pub_filepath, FilenameBuilder, + MediaProcessor, ProcessingManager, + get_process_filename, copy_original, + store_public, request_from_args) from mediagoblin.media_types.ascii import asciitoimage _log = logging.getLogger(__name__) SUPPORTED_EXTENSIONS = ['txt', 'asc', 'nfo'] +MEDIA_TYPE = 'mediagoblin.media_types.ascii' -def sniff_handler(media_file, **kw): - if kw.get('media') is not None: - name, ext = os.path.splitext(kw['media'].filename) - clean_ext = ext[1:].lower() +def sniff_handler(media_file, filename): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) - if clean_ext in SUPPORTED_EXTENSIONS: - return True + name, ext = os.path.splitext(filename) + clean_ext = ext[1:].lower() - return False + if clean_ext in SUPPORTED_EXTENSIONS: + return MEDIA_TYPE + return None -def process_ascii(proc_state): - """Code to process a txt file. Will be run by celery. - A Workbench() represents a local tempory dir. It is automatically - cleaned up when this function exits. +class CommonAsciiProcessor(MediaProcessor): """ - entry = proc_state.entry - workbench = proc_state.workbench - ascii_config = mgg.global_config['media_type:mediagoblin.media_types.ascii'] - # Conversions subdirectory to avoid collisions - conversions_subdir = os.path.join( - workbench.dir, 'conversions') - os.mkdir(conversions_subdir) + Provides a base for various ascii processing steps + """ + acceptable_files = ['original', 'unicode'] + + def common_setup(self): + self.ascii_config = mgg.global_config['plugins'][ + 'mediagoblin.media_types.ascii'] + + # Conversions subdirectory to avoid collisions + self.conversions_subdir = os.path.join( + self.workbench.dir, 'conversions') + os.mkdir(self.conversions_subdir) + + # Pull down and set up the processing file + self.process_filename = get_process_filename( + self.entry, self.workbench, self.acceptable_files) + self.name_builder = FilenameBuilder(self.process_filename) - queued_filepath = entry.queued_media_file - queued_filename = workbench.localized_file( - mgg.queue_store, queued_filepath, - 'source') + self.charset = None - queued_file = file(queued_filename, 'rb') + def copy_original(self): + copy_original( + self.entry, self.process_filename, + self.name_builder.fill('{basename}{ext}')) - with queued_file: - queued_file_charset = chardet.detect(queued_file.read()) + def _detect_charset(self, orig_file): + d_charset = chardet.detect(orig_file.read()) # Only select a non-utf-8 charset if chardet is *really* sure - # Tested with "Feli\x0109an superjaron", which was detecte - if queued_file_charset['confidence'] < 0.9: - interpreted_charset = 'utf-8' + # Tested with "Feli\x0109an superjaron", which was detected + if d_charset['confidence'] < 0.9: + self.charset = 'utf-8' else: - interpreted_charset = queued_file_charset['encoding'] + self.charset = d_charset['encoding'] _log.info('Charset detected: {0}\nWill interpret as: {1}'.format( - queued_file_charset, - interpreted_charset)) + d_charset, + self.charset)) + + # Rewind the file + orig_file.seek(0) + + def store_unicode_file(self): + with file(self.process_filename, 'rb') as orig_file: + self._detect_charset(orig_file) + unicode_filepath = create_pub_filepath(self.entry, + 'ascii-portable.txt') + + with mgg.public_store.get_file(unicode_filepath, 'wb') \ + as unicode_file: + # Decode the original file from its detected charset (or UTF8) + # Encode the unicode instance to ASCII and replace any + # non-ASCII with an HTML entity (&# + unicode_file.write( + unicode(orig_file.read().decode( + self.charset)).encode( + 'ascii', + 'xmlcharrefreplace')) - queued_file.seek(0) # Rewind the queued file + self.entry.media_files['unicode'] = unicode_filepath - thumb_filepath = create_pub_filepath( - entry, 'thumbnail.png') + def generate_thumb(self, font=None, thumb_size=None): + with file(self.process_filename, 'rb') as orig_file: + # If no font kwarg, check config + if not font: + font = self.ascii_config.get('thumbnail_font', None) + if not thumb_size: + thumb_size = (mgg.global_config['media:thumb']['max_width'], + mgg.global_config['media:thumb']['max_height']) - tmp_thumb_filename = os.path.join( - conversions_subdir, thumb_filepath[-1]) + if self._skip_resizing(font, thumb_size): + return - ascii_converter_args = {} + tmp_thumb = os.path.join( + self.conversions_subdir, + self.name_builder.fill('{basename}.thumbnail.png')) - if ascii_config['thumbnail_font']: - ascii_converter_args.update( - {'font': ascii_config['thumbnail_font']}) + ascii_converter_args = {} - converter = asciitoimage.AsciiToImage( - **ascii_converter_args) + # If there is a font from either the config or kwarg, update + # ascii_converter_args + if font: + ascii_converter_args.update( + {'font': self.ascii_config['thumbnail_font']}) - thumb = converter._create_image( - queued_file.read()) + converter = asciitoimage.AsciiToImage( + **ascii_converter_args) - with file(tmp_thumb_filename, 'w') as thumb_file: - thumb.thumbnail( - (mgg.global_config['media:thumb']['max_width'], - mgg.global_config['media:thumb']['max_height']), - Image.ANTIALIAS) - thumb.save(thumb_file) + thumb = converter._create_image( + orig_file.read()) - _log.debug('Copying local file to public storage') - mgg.public_store.copy_local_to_storage( - tmp_thumb_filename, thumb_filepath) + with file(tmp_thumb, 'w') as thumb_file: + thumb.thumbnail( + thumb_size, + Image.ANTIALIAS) + thumb.save(thumb_file) - queued_file.seek(0) + thumb_info = {'font': font, + 'width': thumb_size[0], + 'height': thumb_size[1]} - original_filepath = create_pub_filepath(entry, queued_filepath[-1]) + _log.debug('Copying local file to public storage') + store_public(self.entry, 'thumb', tmp_thumb, + self.name_builder.fill('{basename}.thumbnail.jpg')) - with mgg.public_store.get_file(original_filepath, 'wb') \ - as original_file: - original_file.write(queued_file.read()) + self.entry.set_file_metadata('thumb', **thumb_info) - queued_file.seek(0) # Rewind *again* - unicode_filepath = create_pub_filepath(entry, 'ascii-portable.txt') + def _skip_resizing(self, font, thumb_size): + thumb_info = self.entry.get_file_metadata('thumb') - with mgg.public_store.get_file(unicode_filepath, 'wb') \ - as unicode_file: - # Decode the original file from its detected charset (or UTF8) - # Encode the unicode instance to ASCII and replace any non-ASCII - # with an HTML entity (&# - unicode_file.write( - unicode(queued_file.read().decode( - interpreted_charset)).encode( - 'ascii', - 'xmlcharrefreplace')) + if not thumb_info: + return False - # Remove queued media file from storage and database. - # queued_filepath is in the task_id directory which should - # be removed too, but fail if the directory is not empty to be on - # the super-safe side. - mgg.queue_store.delete_file(queued_filepath) # rm file - mgg.queue_store.delete_dir(queued_filepath[:-1]) # rm dir - entry.queued_media_file = [] + skip = True - media_files_dict = entry.setdefault('media_files', {}) - media_files_dict['thumb'] = thumb_filepath - media_files_dict['unicode'] = unicode_filepath - media_files_dict['original'] = original_filepath + if thumb_info.get('font') != font: + skip = False + elif thumb_info.get('width') != thumb_size[0]: + skip = False + elif thumb_info.get('height') != thumb_size[1]: + skip = False - entry.save() + return skip + + +class InitialProcessor(CommonAsciiProcessor): + """ + Initial processing step for new ascii media + """ + name = "initial" + description = "Initial processing" + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + if not state: + state = entry.state + return state in ( + "unprocessed", "failed") + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--thumb_size', + nargs=2, + metavar=('max_width', 'max_width'), + type=int) + + parser.add_argument( + '--font', + help='the thumbnail font') + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['thumb_size', 'font']) + + def process(self, thumb_size=None, font=None): + self.common_setup() + self.store_unicode_file() + self.generate_thumb(thumb_size=thumb_size, font=font) + self.copy_original() + self.delete_queue_file() + + +class Resizer(CommonAsciiProcessor): + """ + Resizing process steps for processed media + """ + name = 'resize' + description = 'Resize thumbnail' + thumb_size = 'thumb_size' + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + """ + Determine if this media type is eligible for processing + """ + if not state: + state = entry.state + return state in 'processed' + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--thumb_size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + # Needed for gmg reprocess thumbs to work + parser.add_argument( + 'file', + nargs='?', + default='thumb', + choices=['thumb']) + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['thumb_size', 'file']) + + def process(self, thumb_size=None, file=None): + self.common_setup() + self.generate_thumb(thumb_size=thumb_size) + + +class AsciiProcessingManager(ProcessingManager): + def __init__(self): + super(self.__class__, self).__init__() + self.add_processor(InitialProcessor) + self.add_processor(Resizer) diff --git a/mediagoblin/media_types/audio/__init__.py b/mediagoblin/media_types/audio/__init__.py index 4f3ead60..6ad473c8 100644 --- a/mediagoblin/media_types/audio/__init__.py +++ b/mediagoblin/media_types/audio/__init__.py @@ -14,12 +14,36 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from mediagoblin.media_types.audio.processing import process_audio, \ +from mediagoblin.media_types import MediaManagerBase +from mediagoblin.media_types.audio.processing import AudioProcessingManager, \ sniff_handler +from mediagoblin.tools import pluginapi -MEDIA_MANAGER = { - 'human_readable': 'Audio', - 'processor': process_audio, +# Why isn't .ogg in this list? It's still detected, but via sniffing, +# .ogg files could be either video or audio... sniffing determines which. + +ACCEPTED_EXTENSIONS = ["mp3", "flac", "wav", "m4a"] +MEDIA_TYPE = 'mediagoblin.media_types.audio' + + +def setup_plugin(): + config = pluginapi.get_config(MEDIA_TYPE) + + +class AudioMediaManager(MediaManagerBase): + human_readable = "Audio" + display_template = "mediagoblin/media_displays/audio.html" + default_thumb = "images/media_thumbs/image.png" + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, AudioMediaManager + +hooks = { + 'setup': setup_plugin, + 'get_media_type_and_manager': get_media_type_and_manager, 'sniff_handler': sniff_handler, - 'display_template': 'mediagoblin/media_displays/audio.html', - 'accepted_extensions': ['mp3', 'flac', 'wav', 'm4a']} + ('media_manager', MEDIA_TYPE): lambda: AudioMediaManager, + ('reprocess_manager', MEDIA_TYPE): lambda: AudioProcessingManager, +} diff --git a/mediagoblin/media_types/audio/config_spec.ini b/mediagoblin/media_types/audio/config_spec.ini new file mode 100644 index 00000000..743deaa4 --- /dev/null +++ b/mediagoblin/media_types/audio/config_spec.ini @@ -0,0 +1,8 @@ +[plugin_spec] +keep_original = boolean(default=True) +# vorbisenc quality +quality = float(default=0.3) +create_spectrogram = boolean(default=True) +spectrogram_fft_size = integer(default=4096) + + diff --git a/mediagoblin/media_types/audio/processing.py b/mediagoblin/media_types/audio/processing.py index 101b83e5..f12f231e 100644 --- a/mediagoblin/media_types/audio/processing.py +++ b/mediagoblin/media_types/audio/processing.py @@ -14,143 +14,371 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import argparse import logging -from tempfile import NamedTemporaryFile import os from mediagoblin import mg_globals as mgg -from mediagoblin.processing import (create_pub_filepath, BadMediaFail, - FilenameBuilder, ProgressCallback) +from mediagoblin.processing import ( + BadMediaFail, FilenameBuilder, + ProgressCallback, MediaProcessor, ProcessingManager, + request_from_args, get_process_filename, + store_public, copy_original) -from mediagoblin.media_types.audio.transcoders import (AudioTranscoder, - AudioThumbnailer) +from mediagoblin.media_types.audio.transcoders import ( + AudioTranscoder, AudioThumbnailer) _log = logging.getLogger(__name__) +MEDIA_TYPE = 'mediagoblin.media_types.audio' -def sniff_handler(media_file, **kw): + +def sniff_handler(media_file, filename): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) try: transcoder = AudioTranscoder() data = transcoder.discover(media_file.name) except BadMediaFail: _log.debug('Audio discovery raised BadMediaFail') - return False - - if data.is_audio == True and data.is_video == False: - return True + return None - return False + if data.is_audio is True and data.is_video is False: + return MEDIA_TYPE + return None -def process_audio(proc_state): - """Code to process uploaded audio. Will be run by celery. - A Workbench() represents a local tempory dir. It is automatically - cleaned up when this function exits. +class CommonAudioProcessor(MediaProcessor): """ - entry = proc_state.entry - workbench = proc_state.workbench - audio_config = mgg.global_config['media_type:mediagoblin.media_types.audio'] - - queued_filepath = entry.queued_media_file - queued_filename = workbench.localized_file( - mgg.queue_store, queued_filepath, - 'source') - name_builder = FilenameBuilder(queued_filename) - - webm_audio_filepath = create_pub_filepath( - entry, - '{original}.webm'.format( - original=os.path.splitext( - queued_filepath[-1])[0])) - - if audio_config['keep_original']: - with open(queued_filename, 'rb') as queued_file: - original_filepath = create_pub_filepath( - entry, name_builder.fill('{basename}{ext}')) - - with mgg.public_store.get_file(original_filepath, 'wb') as \ - original_file: - _log.debug('Saving original...') - original_file.write(queued_file.read()) - - entry.media_files['original'] = original_filepath - - transcoder = AudioTranscoder() - - with NamedTemporaryFile(dir=workbench.dir) as webm_audio_tmp: - progress_callback = ProgressCallback(entry) - - transcoder.transcode( - queued_filename, - webm_audio_tmp.name, - quality=audio_config['quality'], + Provides a base for various audio processing steps + """ + acceptable_files = ['original', 'best_quality', 'webm_audio'] + + def common_setup(self): + """ + Setup the workbench directory and pull down the original file, add + the audio_config, transcoder, thumbnailer and spectrogram_tmp path + """ + self.audio_config = mgg \ + .global_config['plugins']['mediagoblin.media_types.audio'] + + # Pull down and set up the processing file + self.process_filename = get_process_filename( + self.entry, self.workbench, self.acceptable_files) + self.name_builder = FilenameBuilder(self.process_filename) + + self.transcoder = AudioTranscoder() + self.thumbnailer = AudioThumbnailer() + + def copy_original(self): + if self.audio_config['keep_original']: + copy_original( + self.entry, self.process_filename, + self.name_builder.fill('{basename}{ext}')) + + def _keep_best(self): + """ + If there is no original, keep the best file that we have + """ + if not self.entry.media_files.get('best_quality'): + # Save the best quality file if no original? + if not self.entry.media_files.get('original') and \ + self.entry.media_files.get('webm_audio'): + self.entry.media_files['best_quality'] = self.entry \ + .media_files['webm_audio'] + + def _skip_processing(self, keyname, **kwargs): + file_metadata = self.entry.get_file_metadata(keyname) + skip = True + + if not file_metadata: + return False + + if keyname == 'webm_audio': + if kwargs.get('quality') != file_metadata.get('quality'): + skip = False + elif keyname == 'spectrogram': + if kwargs.get('max_width') != file_metadata.get('max_width'): + skip = False + elif kwargs.get('fft_size') != file_metadata.get('fft_size'): + skip = False + elif keyname == 'thumb': + if kwargs.get('size') != file_metadata.get('size'): + skip = False + + return skip + + def transcode(self, quality=None): + if not quality: + quality = self.audio_config['quality'] + + if self._skip_processing('webm_audio', quality=quality): + return + + progress_callback = ProgressCallback(self.entry) + webm_audio_tmp = os.path.join(self.workbench.dir, + self.name_builder.fill( + '{basename}{ext}')) + + self.transcoder.transcode( + self.process_filename, + webm_audio_tmp, + quality=quality, progress_callback=progress_callback) - transcoder.discover(webm_audio_tmp.name) + self.transcoder.discover(webm_audio_tmp) + + self._keep_best() _log.debug('Saving medium...') - mgg.public_store.get_file(webm_audio_filepath, 'wb').write( - webm_audio_tmp.read()) - - entry.media_files['webm_audio'] = webm_audio_filepath - - # entry.media_data_init(length=int(data.audiolength)) - - if audio_config['create_spectrogram']: - spectrogram_filepath = create_pub_filepath( - entry, - '{original}-spectrogram.jpg'.format( - original=os.path.splitext( - queued_filepath[-1])[0])) - - with NamedTemporaryFile(dir=workbench.dir, suffix='.ogg') as wav_tmp: - _log.info('Creating OGG source for spectrogram') - transcoder.transcode( - queued_filename, - wav_tmp.name, - mux_string='vorbisenc quality={0} ! oggmux'.format( - audio_config['quality'])) - - thumbnailer = AudioThumbnailer() - - with NamedTemporaryFile(dir=workbench.dir, suffix='.jpg') as spectrogram_tmp: - thumbnailer.spectrogram( - wav_tmp.name, - spectrogram_tmp.name, - width=mgg.global_config['media:medium']['max_width'], - fft_size=audio_config['spectrogram_fft_size']) - - _log.debug('Saving spectrogram...') - mgg.public_store.get_file(spectrogram_filepath, 'wb').write( - spectrogram_tmp.read()) - - entry.media_files['spectrogram'] = spectrogram_filepath - - with NamedTemporaryFile(dir=workbench.dir, suffix='.jpg') as thumb_tmp: - thumbnailer.thumbnail_spectrogram( - spectrogram_tmp.name, - thumb_tmp.name, - (mgg.global_config['media:thumb']['max_width'], - mgg.global_config['media:thumb']['max_height'])) - - thumb_filepath = create_pub_filepath( - entry, - '{original}-thumbnail.jpg'.format( - original=os.path.splitext( - queued_filepath[-1])[0])) - - mgg.public_store.get_file(thumb_filepath, 'wb').write( - thumb_tmp.read()) - - entry.media_files['thumb'] = thumb_filepath - else: - entry.media_files['thumb'] = ['fake', 'thumb', 'path.jpg'] - - # Remove queued media file from storage and database. - # queued_filepath is in the task_id directory which should - # be removed too, but fail if the directory is not empty to be on - # the super-safe side. - mgg.queue_store.delete_file(queued_filepath) # rm file - mgg.queue_store.delete_dir(queued_filepath[:-1]) # rm dir - entry.queued_media_file = [] + store_public(self.entry, 'webm_audio', webm_audio_tmp, + self.name_builder.fill('{basename}.medium.webm')) + + self.entry.set_file_metadata('webm_audio', **{'quality': quality}) + + def create_spectrogram(self, max_width=None, fft_size=None): + if not max_width: + max_width = mgg.global_config['media:medium']['max_width'] + if not fft_size: + fft_size = self.audio_config['spectrogram_fft_size'] + + if self._skip_processing('spectrogram', max_width=max_width, + fft_size=fft_size): + return + + wav_tmp = os.path.join(self.workbench.dir, self.name_builder.fill( + '{basename}.ogg')) + + _log.info('Creating OGG source for spectrogram') + self.transcoder.transcode( + self.process_filename, + wav_tmp, + mux_string='vorbisenc quality={0} ! oggmux'.format( + self.audio_config['quality'])) + + spectrogram_tmp = os.path.join(self.workbench.dir, + self.name_builder.fill( + '{basename}-spectrogram.jpg')) + + self.thumbnailer.spectrogram( + wav_tmp, + spectrogram_tmp, + width=max_width, + fft_size=fft_size) + + _log.debug('Saving spectrogram...') + store_public(self.entry, 'spectrogram', spectrogram_tmp, + self.name_builder.fill('{basename}.spectrogram.jpg')) + + file_metadata = {'max_width': max_width, + 'fft_size': fft_size} + self.entry.set_file_metadata('spectrogram', **file_metadata) + + def generate_thumb(self, size=None): + if not size: + max_width = mgg.global_config['media:thumb']['max_width'] + max_height = mgg.global_config['media:thumb']['max_height'] + size = (max_width, max_height) + + if self._skip_processing('thumb', size=size): + return + + thumb_tmp = os.path.join(self.workbench.dir, self.name_builder.fill( + '{basename}-thumbnail.jpg')) + + # We need the spectrogram to create a thumbnail + spectrogram = self.entry.media_files.get('spectrogram') + if not spectrogram: + _log.info('No spectrogram found, we will create one.') + self.create_spectrogram() + spectrogram = self.entry.media_files['spectrogram'] + + spectrogram_filepath = mgg.public_store.get_local_path(spectrogram) + + self.thumbnailer.thumbnail_spectrogram( + spectrogram_filepath, + thumb_tmp, + tuple(size)) + + store_public(self.entry, 'thumb', thumb_tmp, + self.name_builder.fill('{basename}.thumbnail.jpg')) + + self.entry.set_file_metadata('thumb', **{'size': size}) + + +class InitialProcessor(CommonAudioProcessor): + """ + Initial processing steps for new audio + """ + name = "initial" + description = "Initial processing" + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + """ + Determine if this media type is eligible for processing + """ + if not state: + state = entry.state + return state in ( + "unprocessed", "failed") + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--quality', + type=float, + help='vorbisenc quality. Range: -0.1..1') + + parser.add_argument( + '--fft_size', + type=int, + help='spectrogram fft size') + + parser.add_argument( + '--thumb_size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int, + help='minimum size is 100 x 100') + + parser.add_argument( + '--medium_width', + type=int, + help='The width of the spectogram') + + parser.add_argument( + '--create_spectrogram', + action='store_true', + help='Create spectogram and thumbnail, will default to config') + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['create_spectrogram', 'quality', 'fft_size', + 'thumb_size', 'medium_width']) + + def process(self, quality=None, fft_size=None, thumb_size=None, + create_spectrogram=None, medium_width=None): + self.common_setup() + + if not create_spectrogram: + create_spectrogram = self.audio_config['create_spectrogram'] + + self.transcode(quality=quality) + self.copy_original() + + if create_spectrogram: + self.create_spectrogram(max_width=medium_width, fft_size=fft_size) + self.generate_thumb(size=thumb_size) + self.delete_queue_file() + + +class Resizer(CommonAudioProcessor): + """ + Thumbnail and spectogram resizing process steps for processed audio + """ + name = 'resize' + description = 'Resize thumbnail or spectogram' + thumb_size = 'thumb_size' + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + """ + Determine if this media entry is eligible for processing + """ + if not state: + state = entry.state + return state in 'processed' + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--fft_size', + type=int, + help='spectrogram fft size') + + parser.add_argument( + '--thumb_size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int, + help='minimum size is 100 x 100') + + parser.add_argument( + '--medium_width', + type=int, + help='The width of the spectogram') + + parser.add_argument( + 'file', + choices=['thumb', 'spectrogram']) + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['thumb_size', 'file', 'fft_size', 'medium_width']) + + def process(self, file, thumb_size=None, fft_size=None, + medium_width=None): + self.common_setup() + + if file == 'thumb': + self.generate_thumb(size=thumb_size) + elif file == 'spectrogram': + self.create_spectrogram(max_width=medium_width, fft_size=fft_size) + + +class Transcoder(CommonAudioProcessor): + """ + Transcoding processing steps for processed audio + """ + name = 'transcode' + description = 'Re-transcode audio' + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + if not state: + state = entry.state + return state in 'processed' + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--quality', + help='vorbisenc quality. Range: -0.1..1') + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['quality']) + + def process(self, quality=None): + self.common_setup() + self.transcode(quality=quality) + + +class AudioProcessingManager(ProcessingManager): + def __init__(self): + super(self.__class__, self).__init__() + self.add_processor(InitialProcessor) + self.add_processor(Resizer) + self.add_processor(Transcoder) diff --git a/mediagoblin/media_types/audio/transcoders.py b/mediagoblin/media_types/audio/transcoders.py index 84e6af7e..150dad8e 100644 --- a/mediagoblin/media_types/audio/transcoders.py +++ b/mediagoblin/media_types/audio/transcoders.py @@ -122,8 +122,7 @@ class AudioThumbnailer(object): int(start_x), 0, int(stop_x), int(im_h))) - if th.size[0] > th_w or th.size[1] > th_h: - th.thumbnail(thumb_size, Image.ANTIALIAS) + th.thumbnail(thumb_size, Image.ANTIALIAS) th.save(dst) diff --git a/mediagoblin/media_types/blog/__init__.py b/mediagoblin/media_types/blog/__init__.py new file mode 100644 index 00000000..859c2162 --- /dev/null +++ b/mediagoblin/media_types/blog/__init__.py @@ -0,0 +1,121 @@ +#GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import logging +_log = logging.getLogger(__name__) + +from mediagoblin.media_types import MediaManagerBase +from mediagoblin.media_types.blog.models import Blog, BlogPostData + +from mediagoblin.tools import pluginapi + +PLUGIN_DIR = os.path.dirname(__file__) +MEDIA_TYPE = 'mediagoblin.media_types.blogpost' + + +def setup_plugin(): + config = pluginapi.get_config(MEDIA_TYPE) + _log.info("setting up blog media type plugin.") + + routes = [ + #blog_create + ('mediagoblin.media_types.blog.create', + '/u/<string:user>/b/create/', + 'mediagoblin.media_types.blog.views:blog_edit' + ), + #blog_edit + ('mediagoblin.media_types.blog.edit', + '/u/<string:user>/b/<string:blog_slug>/edit/', + 'mediagoblin.media_types.blog.views:blog_edit' + ), + #blog post create + ('mediagoblin.media_types.blog.blogpost.create', + '/u/<string:user>/b/<string:blog_slug>/p/create/', + 'mediagoblin.media_types.blog.views:blogpost_create' + ), + #blog post edit + ('mediagoblin.media_types.blog.blogpost.edit', + '/u/<string:user>/b/<string:blog_slug>/p/<string:blog_post_slug>/edit/', + 'mediagoblin.media_types.blog.views:blogpost_edit' + ), + #blog collection dashboard in case of multiple blogs + ('mediagoblin.media_types.blog.blog_admin_dashboard', + '/u/<string:user>/b/dashboard/', + 'mediagoblin.media_types.blog.views:blog_dashboard' + ), + #blog dashboard + ('mediagoblin.media_types.blog.blog-dashboard', + '/u/<string:user>/b/<string:blog_slug>/dashboard/', + 'mediagoblin.media_types.blog.views:blog_dashboard' + ), + #blog post listing view + ('mediagoblin.media_types.blog.blog_post_listing', + '/u/<string:user>/b/<string:blog_slug>/', + 'mediagoblin.media_types.blog.views:blog_post_listing' + ), + #blog post draft view + ('mediagoblin.media_types.blog.blogpost_draft_view', + '/u/<string:user>/b/<string:blog_slug>/p/<string:blog_post_slug>/draft/', + 'mediagoblin.media_types.blog.views:draft_view' + ), + #blog delete view + ('mediagoblin.media_types.blog.blog_delete', + '/u/<string:user>/b/<string:blog_slug>/delete/', + 'mediagoblin.media_types.blog.views:blog_delete' + ), + # blog about view + ('mediagoblin.media_types.blog.blog_about', + '/u/<string:user>/b/<string:blog_slug>/about/', + 'mediagoblin.media_types.blog.views:blog_about_view' + )] + + + pluginapi.register_routes(routes) + pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates')) + pluginapi.register_template_hooks({"user_profile": "mediagoblin/blog/url_to_blogs_dashboard.html", + "blog_dashboard_home": "mediagoblin/blog/url_to_dashboard.html", + }) + + +class BlogPostMediaManager(MediaManagerBase): + human_readable = "Blog Post" + display_template = "mediagoblin/media_displays/blogpost.html" + default_thumb = "images/media_thumbs/blogpost.jpg" + + def get_blog_by_blogpost(self): + blog_post_data = BlogPostData.query.filter_by(media_entry=self.entry.id).first() + blog = Blog.query.filter_by(id=blog_post_data.blog).first() + return blog + +def add_to_user_home_context(context): + """Inject a user's blogs into a (user home page) template context""" + blogs = context['request'].db.Blog.query.filter_by(author=context['user'].id) + + if blogs.count(): + context['blogs'] = blogs + else: + context['blogs'] = None + return context + + +hooks = { + 'setup': setup_plugin, + ('media_manager', MEDIA_TYPE): lambda: BlogPostMediaManager, + # Inject blog context on user profile page + ("mediagoblin.user_pages.user_home", + "mediagoblin/user_pages/user.html"): add_to_user_home_context +} diff --git a/mediagoblin/media_types/blog/config_spec.ini b/mediagoblin/media_types/blog/config_spec.ini new file mode 100644 index 00000000..77038f47 --- /dev/null +++ b/mediagoblin/media_types/blog/config_spec.ini @@ -0,0 +1,2 @@ +[plugin_spec] +max_blog_count = integer(default=4) diff --git a/mediagoblin/media_types/blog/forms.py b/mediagoblin/media_types/blog/forms.py new file mode 100644 index 00000000..1cc41a02 --- /dev/null +++ b/mediagoblin/media_types/blog/forms.py @@ -0,0 +1,46 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import wtforms + +from mediagoblin.tools.text import tag_length_validator, TOO_LONG_TAG_WARNING +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.tools.licenses import licenses_as_choices + +class BlogPostEditForm(wtforms.Form): + title = wtforms.TextField(_('Title'), + [wtforms.validators.Length(min=0, max=500)]) + description = wtforms.TextAreaField(_('Description')) + tags = wtforms.TextField(_('Tags'), [tag_length_validator], + description="Seperate tags by commas.") + license = wtforms.SelectField(_('License'), + [wtforms.validators.Optional(),], choices=licenses_as_choices()) + +class BlogEditForm(wtforms.Form): + title = wtforms.TextField(_('Title'), + [wtforms.validators.Length(min=0, max=500)]) + description = wtforms.TextAreaField(_('Description')) + + +class ConfirmDeleteForm(wtforms.Form): + confirm = wtforms.BooleanField( + _('I am sure I want to delete this')) + + + + + + diff --git a/mediagoblin/media_types/blog/lib.py b/mediagoblin/media_types/blog/lib.py new file mode 100644 index 00000000..62696b55 --- /dev/null +++ b/mediagoblin/media_types/blog/lib.py @@ -0,0 +1,49 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. + + +def check_blog_slug_used(author_id, slug, ignore_b_id=None): + from mediagoblin.media_types.blog.models import Blog + query = Blog.query.filter_by(author=author_id, slug=slug) + if ignore_b_id: + query = query.filter(Blog.id != ignore_b_id) + does_exist = query.first() is not None + return does_exist + +def may_edit_blogpost(request, blog): + if request.user.has_privilege(u'admin') or request.user.id == blog.author: + return True + return False + +def set_blogpost_state(request, blogpost): + if request.form['status'] == 'Publish': + blogpost.state = u'processed' + else: + blogpost.state = u'failed' + +def get_all_blogposts_of_blog(request, blog, state=None): + blog_posts_list = [] + blog_post_data = request.db.BlogPostData.query.filter_by(blog=blog.id).all() + for each_blog_post_data in blog_post_data: + blog_post = each_blog_post_data.get_media_entry + if state == None: + blog_posts_list.append(blog_post) + if blog_post.state == state: + blog_posts_list.append(blog_post) + blog_posts_list.reverse() + return blog_posts_list + + diff --git a/mediagoblin/media_types/blog/models.py b/mediagoblin/media_types/blog/models.py new file mode 100644 index 00000000..7c55e359 --- /dev/null +++ b/mediagoblin/media_types/blog/models.py @@ -0,0 +1,79 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import datetime + +from mediagoblin.db.base import Base +from mediagoblin.db.base import Session +from mediagoblin.db.models import Collection, User, MediaEntry +from mediagoblin.db.mixin import GenerateSlugMixin + +from mediagoblin.media_types.blog.lib import check_blog_slug_used + +from mediagoblin.tools.text import cleaned_markdown_conversion + +from sqlalchemy import ( + Column, Integer, ForeignKey, Unicode, UnicodeText, DateTime) +from sqlalchemy.orm import relationship, backref + + +class BlogMixin(GenerateSlugMixin): + def check_slug_used(self, slug): + return check_blog_slug_used(self.author, slug, self.id) + +class Blog(Base, BlogMixin): + __tablename__ = "mediatype__blogs" + id = Column(Integer, primary_key=True) + title = Column(Unicode) + description = Column(UnicodeText) + author = Column(Integer, ForeignKey(User.id), nullable=False, index=True) #similar to uploader + created = Column(DateTime, nullable=False, default=datetime.datetime.now, index=True) + slug = Column(Unicode) + + + def get_all_blog_posts(self, state=None): + blog_posts = Session.query(MediaEntry).join(BlogPostData)\ + .filter(BlogPostData.blog == self.id) + if state is not None: + blog_posts = blog_posts.filter(MediaEntry.state==state) + return blog_posts + + def delete(self, **kwargs): + all_posts = self.get_all_blog_posts() + for post in all_posts: + post.delete(del_orphan_tags=False, commit=False) + from mediagoblin.db.util import clean_orphan_tags + clean_orphan_tags(commit=False) + super(Blog, self).delete(**kwargs) + + + + +BACKREF_NAME = "blogpost__media_data" + +class BlogPostData(Base): + __tablename__ = "blogpost__mediadata" + + # The primary key *and* reference to the main media_entry + media_entry = Column(Integer, ForeignKey('core__media_entries.id'), primary_key=True) + blog = Column(Integer, ForeignKey('mediatype__blogs.id'), nullable=False) + get_media_entry = relationship("MediaEntry", + backref=backref(BACKREF_NAME, uselist=False, + cascade="all, delete-orphan")) + + +DATA_MODEL = BlogPostData +MODELS = [BlogPostData, Blog] diff --git a/mediagoblin/init/celery/from_tests.py b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_about.html index 3149e1ba..ed2611d6 100644 --- a/mediagoblin/init/celery/from_tests.py +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_about.html @@ -1,3 +1,4 @@ +{# # GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # @@ -13,21 +14,25 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +#} -import os +{% extends "mediagoblin/base.html" %} -from mediagoblin.tests.tools import TEST_APP_CONFIG -from mediagoblin.init.celery.from_celery import setup_self +{% block mediagoblin_head%} +<style type = "text/css"> + h2 { font-weight: bold; text-transform:capitalize; } + #blogs_list {border-collapse:separate; border-spacing: 40px 0px ;} +</style> +{% endblock %} -OUR_MODULENAME = __name__ -CELERY_SETUP = False +{% block mediagoblin_content %} + <h2> {{ blog.title }}</h2> + <br/> + <p> {{ blog.description|safe }}</p> + <br/> + <em>{{ blog.created.strftime("%d %b, %Y") }}</em> + + <em>posts({{ blogpost_count }})</em> +{% endblock mediagoblin_content %} - -if os.environ.get('CELERY_CONFIG_MODULE') == OUR_MODULENAME: - if CELERY_SETUP: - pass - else: - setup_self(check_environ_for_conf=False, module_name=OUR_MODULENAME, - default_conf_file=TEST_APP_CONFIG) - CELERY_SETUP = True diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_admin_dashboard.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_admin_dashboard.html new file mode 100644 index 00000000..1316083b --- /dev/null +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_admin_dashboard.html @@ -0,0 +1,110 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% extends "mediagoblin/base.html" %} +{% from "mediagoblin/utils/pagination.html" import render_pagination %} + +{% block title -%} +{{blog.title}} Dashboard — {{ super() }} +{%- endblock title %} + +{% block mediagoblin_head%} +<style type = "text/css"> + td > a { text-decoration:none; font-weight: bold; } +</style> +{% endblock %} + + +{% block mediagoblin_content %} +<h1 style="text-transform:capitalize"> {{blog.title}}</h1> +<p> + {{blog.description|safe}} +</p> +<p> + {% set blogpost_create_url = request.urlgen('mediagoblin.media_types.blog.blogpost.create', + blog_slug=blog.slug, + user=request.user.username) %} +<a class="button_action" href="{{ blogpost_create_url }}"> +{%- trans %}Add Blog Post{% endtrans -%} +</a> +· + {% set blog_edit_url = request.urlgen('mediagoblin.media_types.blog.edit', + blog_slug=blog.slug, + user=request.user.username) %} +<a class="button_action" href="{{ blog_edit_url }}"> +{%- trans %}Edit Blog{% endtrans -%} +</a> +· + {% set blog_delete_url = request.urlgen('mediagoblin.media_types.blog.blog_delete', + blog_slug=blog.slug, + user=request.user.username) %} +<a class="button_action" href="{{ blog_delete_url }}"> +{%- trans %}Delete Blog{% endtrans -%} +</a> +</p> +<h2> Blog Post Entries </h2> + {% if blog_posts_list.count() %} + <table class="media_panel processing"> + <tr> + <th>Title</th> + <th>submitted</th> + <th></th> + </tr> + {% for blog_post in blog_posts_list %} + <tr> + {% if blog_post.state == 'processed' %} + <td><a href="{{ blog_post.url_for_self(request.urlgen) }}">{{ blog_post.title }}</a></td> + {% else %} + {% set draft_url = request.urlgen('mediagoblin.media_types.blog.blogpost_draft_view', + blog_slug=blog.slug, user=request.user.username, + blog_post_slug=blog_post.slug) %} + <td><a href="{{ draft_url }}">{{ blog_post.title }}</a></td> + {% endif %} + <td>{{ blog_post.created.strftime("%F %R") }}</td> + + {% if blog_post.state == 'processed' %} + <td><h6><em>Published</em></h6></td> + {% else %} + <td><h6><em>Draft</em></h6></td> + {% endif %} + {% set blogpost_edit_url = request.urlgen('mediagoblin.media_types.blog.blogpost.edit', + blog_slug=blog.slug, user=request.user.username, + blog_post_slug=blog_post.slug) %} + {% set blogpost_delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete', + user= blog_post.get_uploader.username, + media_id=blog_post.id) %} + <td> + <a class="button_action" href="{{ blogpost_edit_url }}">{% trans %}Edit{% endtrans %}</a> + <a class="button_action" href="{{ blogpost_delete_url }}">{% trans %}Delete{% endtrans %}</a> + </td> + </tr> + {% endfor %} + </table> + {% set blogpost_listing_url = request.urlgen('mediagoblin.media_types.blog.blog_post_listing', + blog_slug=blog_slug, user=user.username) %} + <br/> + <br/> + <a href="{{ blogpost_listing_url}}">{% trans %}<em> Go to list view </em>{% endtrans %}</a> + {% else %} + {% trans %} No blog post yet. {% endtrans %} + {% endif %} + {{ render_pagination(request, pagination) }} +{% endblock %} + + + diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_confirm_delete.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_confirm_delete.html new file mode 100644 index 00000000..f98764be --- /dev/null +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_confirm_delete.html @@ -0,0 +1,53 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block mediagoblin_content %} + + <form action="{{ request.urlgen('mediagoblin.media_types.blog.blog_delete', + user=request.user.username, + blog_slug=blog.slug) }}" + method="POST" enctype="multipart/form-data"> + <div class="form_box"> + <h1> + {%- trans title=blog.title -%} + Really delete {{ title }}? + {%- endtrans %} + </h1> + + <br/> + + <p class="delete_checkbox_box"> + {{ form.confirm }} + {{ wtforms_util.render_label(form.confirm) }} + </p> + + <div class="form_submit_buttons"> + {# TODO: This isn't a button really... might do unexpected things :) #} + {% set blog_dashboard_url = request.urlgen('mediagoblin.media_types.blog.blog-dashboard', + blog_slug=blog.slug, user=request.user.username) %} + + <a class="button_action" href="{{ blog_dashboard_url }}">{% trans %}Cancel{% endtrans %}</a> + <input type="submit" value="{% trans %}Delete permanently{% endtrans %}" class="button_form" /> + {{ csrf_token }} + </div> + </div> + </form> +{% endblock %} diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_edit_create.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_edit_create.html new file mode 100644 index 00000000..f4bbcb8f --- /dev/null +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_edit_create.html @@ -0,0 +1,41 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block mediagoblin_content %} + <form action="" + method="POST" enctype="multipart/form-data"> + <div class="blog_form_box_xl"> + <h1>{% trans %}Create/Edit a Blog{% endtrans %}</h1> + <b>Title</b> + <div class="blog_form_field_input input"> + <h3>{{ form.title}}</h3> + </div> + <b>Description</b> + <div class="blog_form_field_input textarea"> + <h3>{{form.description|safe}}</h3> + </div> + <div class="form_submit_buttons"> + {{ csrf_token }} + <input type="submit" value="{% trans %}Add{% endtrans %}" class="button_form" /> + </div> + </div> + </form> +{% endblock %} diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_edit_create.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_edit_create.html new file mode 100644 index 00000000..e1f6ed90 --- /dev/null +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_edit_create.html @@ -0,0 +1,53 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans %}Create/Edit a blog post.{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + <form action="" method="POST"> + <div class="blog_form_box_xl"> + <h1>{% trans %}Create/Edit a Blog Post.{% endtrans %}</h1> + <b>Title</b> + <div class="blog_form_field_input input"> + <h3>{{ form.title}}</h3> + </div> + <b>Description</b> + <div class="blog_form_field_input textarea"> + <h3>{{form.description|safe}}</h3> + </div> + <b>Tags</b> + <div class="blog_form_field_input input"> + <h3>{{form.tags}}</h3> + </div> + <b>License</b> + <div class="blog_form_field_input input"> + <h3>{{form.license}}</h3> + </div> + <div class="form_submit_buttons"> + {{ csrf_token }} + <input type="submit" name="status" value="Publish" class="button_form"> + <input type="submit" name="status" value="Save as Draft" class="button_form"> + </div> + </div> + </form> +{% endblock %} diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_listing.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_listing.html new file mode 100644 index 00000000..8d7a405e --- /dev/null +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_listing.html @@ -0,0 +1,66 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} +{% from "mediagoblin/utils/pagination.html" import render_pagination %} +{% set blog_owner_name = blog_owner.username %} +{% block title -%} + {% trans %}{{ blog_owner_name }}'s Blog{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_head -%} + <style type="text/css"> + h4 {margin:0; padding : 0; + font-size:.7 em;} + a{text-decoration:none; + text-transform:capitalize + } + + </style> +{%- endblock %} + +{% block mediagoblin_content %} + <div class="b_list_owner"> <h1><font color="black"> {{ blog.title }} <font size="2">by {{ blog_owner_name }}</font> </font></h1></div> + <div> + {% for post in blog_posts %} + <div class="b_listing_title"><a href="{{ post.url_for_self(request.urlgen) }}"> + <h2><font color="black">{{ post.title }}</font></h2></a> + </div> + <h4 align="right">{{ post.created.strftime("%d %b, %Y") }}</h4> + {% if post.tags %} + {% for tag in post.tags %} + <a href="{{ request.urlgen( + 'mediagoblin.user_pages.user_tag_gallery', + tag=tag['slug'], + user=post.get_uploader.username) }}">{{ tag['name'] }} |</a> + {% endfor %} + {% endif %} + <div class="b_list_des"> <p>{{ post.description|safe }} </p></div> + </br> + </br> + {% endfor %} + </div> + <br/> + <br/> + {% set blog_about_url = request.urlgen('mediagoblin.media_types.blog.blog_about', + blog_slug=blog.slug, user=blog_owner_name) %} + <a style="text-decoration:underline" href="{{ blog_about_url}}">About Blog</a> + <br/> + {{ render_pagination(request, pagination) }} +{% endblock %} diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blogpost_draft_view.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blogpost_draft_view.html new file mode 100644 index 00000000..7c634877 --- /dev/null +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blogpost_draft_view.html @@ -0,0 +1,42 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% extends 'mediagoblin/base.html' %} + +{% block mediagoblin_head %} + {{ super() }} +{% endblock %} + +{% block mediagoblin_content %} +<h1> {{ blogpost.title}}</h1> +<p>{{ blogpost.description|safe}}</p> + +{% set blogpost_edit_url = request.urlgen('mediagoblin.media_types.blog.blogpost.edit', + blog_slug=blog.slug, user=request.user.username, + blog_post_slug=blogpost.slug) %} +{% set blogpost_delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete', + user= blogpost.get_uploader.username, + media_id=blogpost.id) %} + <a class="button_action" href="{{ blogpost_edit_url }}">{% trans %}Edit{% endtrans %}</a> + <a class="button_action" href="{{ blogpost_delete_url }}">{% trans %}Delete{% endtrans %}</a> + +{% endblock %} + + + + diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/list_of_blogs.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/list_of_blogs.html new file mode 100644 index 00000000..f19a9225 --- /dev/null +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/list_of_blogs.html @@ -0,0 +1,69 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% extends "mediagoblin/base.html" %} + + +{% block mediagoblin_head%} +<style type = "text/css"> + table a { text-decoration:none; font-weight: bold; text-transform:capitalize; } + #blogs_list {border-collapse:separate; border-spacing: 40px 0px ;} +</style> +{% endblock %} + +{% block mediagoblin_content %} + {% if blogs %} + <h2>My Blogs</h2> + <table id="blogs_list"> + {% for blog in blogs %} + {% set others_blog_url = request.urlgen('mediagoblin.media_types.blog.blog_post_listing', + blog_slug=blog.slug, user=user.username) %} + + <tr> + {% if not request.user or request.user.username != user.username%} + <td><a href="{{ others_blog_url }}">{{ blog.title }}</a></td> + {% else %} + {% set my_blog_url = request.urlgen('mediagoblin.media_types.blog.blog-dashboard', + blog_slug=blog.slug, user=request.user.username) %} + <td><a href="{{ my_blog_url }}">{{ blog.title }}</a></td> + {% endif %} + <td> </td> + <td><a class="button_action" href="{{ others_blog_url }}">{% trans %}View{% endtrans %}</a></td> + </tr> + {% endfor %} + </table> + {% else %} + + {% if request.user and request.user.username==user.username %} + <p>You have not created any blog yet.</p> + {% else %} + <p>No blog has been created by <strong>{{ user.username }}</strong>yet.</p> + {% endif %} + {% endif %} + <br/> + <br/> + <br/> + {% if blogs.__len__() <max_blog_count and request.user and request.user.username==user.username %} + {% set blog_create_url = request.urlgen('mediagoblin.media_types.blog.create', + user=request.user.username) %} + + <a class="button_action" href="{{ blog_create_url }}">{% trans %}Create a Blog{% endtrans %}</a> + {% endif %} + +{% endblock mediagoblin_content %} + diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogs_dashboard.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogs_dashboard.html new file mode 100644 index 00000000..839b8a5a --- /dev/null +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogs_dashboard.html @@ -0,0 +1,24 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#}{#This injects the URL to a user's blog dashboard on her profile.#} +{%if blogs %} +<h3>Blog</h3> +{% set blogs_url = request.urlgen('mediagoblin.media_types.blog.blog_admin_dashboard', + user=user.username) %} + +<p><a href="{{ blogs_url }}"><em>Go to user's blog</em></a></p> +{%endif%} diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_dashboard.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_dashboard.html new file mode 100644 index 00000000..bc92c419 --- /dev/null +++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_dashboard.html @@ -0,0 +1,21 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + <a href="{{ request.urlgen('mediagoblin.media_types.blog.blog_admin_dashboard', + user=request.user.username) }}"> + {%- trans %} Blog Dashboard {% endtrans -%} + </a> · diff --git a/mediagoblin/media_types/blog/views.py b/mediagoblin/media_types/blog/views.py new file mode 100644 index 00000000..042881e4 --- /dev/null +++ b/mediagoblin/media_types/blog/views.py @@ -0,0 +1,379 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import logging +_log = logging.getLogger(__name__) + +from datetime import datetime + +from werkzeug.exceptions import Forbidden +from mediagoblin.tools import pluginapi + +from mediagoblin import mg_globals + +from mediagoblin.media_types.blog import forms as blog_forms +from mediagoblin.media_types.blog.models import Blog, BlogPostData +from mediagoblin.media_types.blog.lib import may_edit_blogpost, set_blogpost_state, get_all_blogposts_of_blog + +from mediagoblin.messages import add_message, SUCCESS, ERROR +from mediagoblin.decorators import (require_active_login, active_user_from_url, + get_media_entry_by_id, user_may_alter_collection, + get_user_collection, uses_pagination) +from mediagoblin.tools.pagination import Pagination +from mediagoblin.tools.response import (render_to_response, + redirect, render_404) +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.template import render_template +from mediagoblin.tools.text import ( + convert_to_tag_list_of_dicts, media_tags_as_string, clean_html, + cleaned_markdown_conversion) + +from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used +from mediagoblin.db.models import User, Collection, MediaEntry + +from mediagoblin.notifications import add_comment_subscription + + +@require_active_login +def blog_edit(request): + """ + View for editing an existing blog or creating a new blog + if user have not exceeded maximum allowed acount of blogs. + """ + url_user = request.matchdict.get('user', None) + blog_slug = request.matchdict.get('blog_slug', None) + + config = pluginapi.get_config('mediagoblin.media_types.blog') + max_blog_count = config['max_blog_count'] + form = blog_forms.BlogEditForm(request.form) + # creating a blog + if not blog_slug: + if Blog.query.filter_by(author=request.user.id).count()<max_blog_count: + if request.method=='GET': + return render_to_response( + request, + 'mediagoblin/blog/blog_edit_create.html', + {'form': form, + 'user' : request.user, + 'app_config': mg_globals.app_config}) + + if request.method=='POST' and form.validate(): + _log.info("Here") + blog = request.db.Blog() + blog.title = unicode(form.title.data) + blog.description = unicode(cleaned_markdown_conversion((form.description.data))) + blog.author = request.user.id + blog.generate_slug() + + blog.save() + return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", + user=request.user.username + ) + else: + add_message(request, ERROR, "Welcome! You already have created \ + maximum number of blogs.") + return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", + user=request.user.username) + + + #Blog already exists. + else: + blog = request.db.Blog.query.filter_by(slug=blog_slug).first() + if not blog: + return render_404(request) + if request.method == 'GET': + defaults = dict( + title = blog.title, + description = cleaned_markdown_conversion(blog.description), + author = request.user.id) + + form = blog_forms.BlogEditForm(**defaults) + + return render_to_response( + request, + 'mediagoblin/blog/blog_edit_create.html', + {'form': form, + 'user': request.user, + 'app_config': mg_globals.app_config}) + else: + if request.method == 'POST' and form.validate(): + blog.title = unicode(form.title.data) + blog.description = unicode(cleaned_markdown_conversion((form.description.data))) + blog.author = request.user.id + blog.generate_slug() + + blog.save() + add_message(request, SUCCESS, "Your blog is updated.") + return redirect(request, "mediagoblin.media_types.blog.blog-dashboard", + user=request.user.username, + blog_slug=blog.slug) + + +@require_active_login +def blogpost_create(request): + + form = blog_forms.BlogPostEditForm(request.form, license=request.user.license_preference) + + if request.method == 'POST' and form.validate(): + blog_slug = request.matchdict.get('blog_slug') + blog = request.db.Blog.query.filter_by(slug=blog_slug, + author=request.user.id).first() + if not blog: + return render_404(request) + + blogpost = request.db.MediaEntry() + blogpost.media_type = 'mediagoblin.media_types.blogpost' + blogpost.title = unicode(form.title.data) + blogpost.description = unicode(cleaned_markdown_conversion((form.description.data))) + blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data) + blogpost.license = unicode(form.license.data) or None + blogpost.uploader = request.user.id + blogpost.generate_slug() + + set_blogpost_state(request, blogpost) + blogpost.save() + + # connect this blogpost to its blog + blog_post_data = request.db.BlogPostData() + blog_post_data.blog = blog.id + blog_post_data.media_entry = blogpost.id + blog_post_data.save() + + add_message(request, SUCCESS, _('Woohoo! Submitted!')) + add_comment_subscription(request.user, blogpost) + return redirect(request, "mediagoblin.media_types.blog.blog-dashboard", + user=request.user.username, + blog_slug=blog.slug) + + return render_to_response( + request, + 'mediagoblin/blog/blog_post_edit_create.html', + {'form': form, + 'app_config': mg_globals.app_config, + 'user': request.user.username}) + + +@require_active_login +def blogpost_edit(request): + + blog_slug = request.matchdict.get('blog_slug', None) + blog_post_slug = request.matchdict.get('blog_post_slug', None) + + blogpost = request.db.MediaEntry.query.filter_by(slug=blog_post_slug, uploader=request.user.id).first() + blog = request.db.Blog.query.filter_by(slug=blog_slug, author=request.user.id).first() + + if not blogpost or not blog: + return render_404(request) + + defaults = dict( + title = blogpost.title, + description = cleaned_markdown_conversion(blogpost.description), + tags=media_tags_as_string(blogpost.tags), + license=blogpost.license) + + form = blog_forms.BlogPostEditForm(request.form, **defaults) + if request.method == 'POST' and form.validate(): + blogpost.title = unicode(form.title.data) + blogpost.description = unicode(cleaned_markdown_conversion((form.description.data))) + blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data) + blogpost.license = unicode(form.license.data) + set_blogpost_state(request, blogpost) + blogpost.generate_slug() + blogpost.save() + + add_message(request, SUCCESS, _('Woohoo! edited blogpost is submitted')) + return redirect(request, "mediagoblin.media_types.blog.blog-dashboard", + user=request.user.username, + blog_slug=blog.slug) + + return render_to_response( + request, + 'mediagoblin/blog/blog_post_edit_create.html', + {'form': form, + 'app_config': mg_globals.app_config, + 'user': request.user.username, + 'blog_post_slug': blog_post_slug + }) + + +@active_user_from_url +@uses_pagination +def blog_dashboard(request, page, url_user=None): + """ + Dashboard for a blog, only accessible to + the owner of the blog. + """ + blog_slug = request.matchdict.get('blog_slug', None) + blogs = request.db.Blog.query.filter_by(author=url_user.id) + config = pluginapi.get_config('mediagoblin.media_types.blog') + max_blog_count = config['max_blog_count'] + if request.user and (request.user.id == url_user.id or request.user.has_privilege(u'admin')): + if blog_slug: + blog = blogs.filter(Blog.slug==blog_slug).first() + if not blog: + return render_404(request) + else: + blog_posts_list = blog.get_all_blog_posts().order_by(MediaEntry.created.desc()) + pagination = Pagination(page, blog_posts_list) + pagination.per_page = 15 + blog_posts_on_a_page = pagination() + if may_edit_blogpost(request, blog): + return render_to_response( + request, + 'mediagoblin/blog/blog_admin_dashboard.html', + {'blog_posts_list': blog_posts_on_a_page, + 'blog_slug':blog_slug, + 'blog':blog, + 'user':url_user, + 'pagination':pagination + }) + if not request.user or request.user.id != url_user.id or not blog_slug: + blogs = blogs.all() + return render_to_response( + request, + 'mediagoblin/blog/list_of_blogs.html', + { + 'blogs':blogs, + 'user':url_user, + 'max_blog_count':max_blog_count + }) + + +@active_user_from_url +@uses_pagination +def blog_post_listing(request, page, url_user=None): + """ + Page, listing all the blog posts of a particular blog. + """ + blog_slug = request.matchdict.get('blog_slug', None) + blog = request.db.Blog.query.filter_by(slug=blog_slug).first() + if not blog: + return render_404(request) + + all_blog_posts = blog.get_all_blog_posts(u'processed').order_by(MediaEntry.created.desc()) + pagination = Pagination(page, all_blog_posts) + pagination.per_page = 8 + blog_posts_on_a_page = pagination() + + return render_to_response( + request, + 'mediagoblin/blog/blog_post_listing.html', + {'blog_posts': blog_posts_on_a_page, + 'pagination': pagination, + 'blog_owner': url_user, + 'blog':blog + }) + + +@require_active_login +def draft_view(request): + + blog_slug = request.matchdict.get('blog_slug', None) + blog_post_slug = request.matchdict.get('blog_post_slug', None) + user = request.matchdict.get('user') + + blog = request.db.Blog.query.filter_by(author=request.user.id, slug=blog_slug).first() + blogpost = request.db.MediaEntry.query.filter_by(state = u'failed', uploader=request.user.id, slug=blog_post_slug).first() + + if not blog or not blogpost: + return render_404(request) + + return render_to_response( + request, + 'mediagoblin/blog/blogpost_draft_view.html', + {'blogpost':blogpost, + 'blog': blog + }) + + +@require_active_login +def blog_delete(request, **kwargs): + """ + Deletes a blog and media entries, tags associated with it. + """ + url_user = request.matchdict.get('user') + owner_user = request.db.User.query.filter_by(username=url_user).first() + + blog_slug = request.matchdict.get('blog_slug', None) + blog = request.db.Blog.query.filter_by(slug=blog_slug, author=owner_user.id).first() + if not blog: + return render_404(reequest) + + form = blog_forms.ConfirmDeleteForm(request.form) + if request.user.id == blog.author or request.user.has_privilege(u'admin'): + if request.method == 'POST' and form.validate(): + if form.confirm.data is True: + blog.delete() + add_message( + request, SUCCESS, _('You deleted the Blog.')) + return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", + user=request.user.username) + else: + add_message( + request, ERROR, + _("The media was not deleted because you didn't check that you were sure.")) + return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", + user=request.user.username) + else: + if request.user.has_privilege(u'admin'): + add_message( + request, WARNING, + _("You are about to delete another user's Blog. " + "Proceed with caution.")) + return render_to_response( + request, + 'mediagoblin/blog/blog_confirm_delete.html', + {'blog':blog, + 'form':form + }) + else: + add_message( + request, ERROR, + _("The blog was not deleted because you have no rights.")) + return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard", + user=request.user.username) + + +def blog_about_view(request): + """ + Page containing blog description and statistics + """ + blog_slug = request.matchdict.get('blog_slug', None) + url_user = request.matchdict.get('user', None) + + user = request.db.User.query.filter_by(username=url_user).first() + blog = request.db.Blog.query.filter_by(author=user.id, slug=blog_slug).first() + + if not user or not blog: + return render_404(request) + + else: + blog_posts_processed = blog.get_all_blog_posts(u'processed').count() + return render_to_response( + request, + 'mediagoblin/blog/blog_about.html', + {'user': user, + 'blog': blog, + 'blogpost_count': blog_posts_processed + }) + + + + + + + + diff --git a/mediagoblin/media_types/image/__init__.py b/mediagoblin/media_types/image/__init__.py index 15cc8dda..f5b49f01 100644 --- a/mediagoblin/media_types/image/__init__.py +++ b/mediagoblin/media_types/image/__init__.py @@ -13,20 +13,60 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import datetime +import logging from mediagoblin.media_types import MediaManagerBase -from mediagoblin.media_types.image.processing import process_image, \ - sniff_handler +from mediagoblin.media_types.image.processing import sniff_handler, \ + ImageProcessingManager +_log = logging.getLogger(__name__) + + +ACCEPTED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "tiff"] +MEDIA_TYPE = 'mediagoblin.media_types.image' + +def setup_plugin(): + config = pluginapi.get_config(MEDIA_TYPE) + class ImageMediaManager(MediaManagerBase): human_readable = "Image" - processor = staticmethod(process_image) - sniff_handler = staticmethod(sniff_handler) display_template = "mediagoblin/media_displays/image.html" default_thumb = "images/media_thumbs/image.png" - accepted_extensions = ["jpg", "jpeg", "png", "gif", "tiff"] + media_fetch_order = [u'medium', u'original', u'thumb'] - -MEDIA_MANAGER = ImageMediaManager + def get_original_date(self): + """ + Get the original date and time from the EXIF information. Returns + either a datetime object or None (if anything goes wrong) + """ + if not self.entry.media_data or not self.entry.media_data.exif_all: + return None + + try: + # Try wrapped around all since exif_all might be none, + # EXIF DateTimeOriginal or printable might not exist + # or strptime might not be able to parse date correctly + exif_date = self.entry.media_data.exif_all[ + 'EXIF DateTimeOriginal']['printable'] + original_date = datetime.datetime.strptime( + exif_date, + '%Y:%m:%d %H:%M:%S') + return original_date + except (KeyError, ValueError): + return None + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, ImageMediaManager + + +hooks = { + 'get_media_type_and_manager': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + ('media_manager', MEDIA_TYPE): lambda: ImageMediaManager, + ('reprocess_manager', MEDIA_TYPE): lambda: ImageProcessingManager, +} diff --git a/mediagoblin/media_types/image/config_spec.ini b/mediagoblin/media_types/image/config_spec.ini new file mode 100644 index 00000000..08111df2 --- /dev/null +++ b/mediagoblin/media_types/image/config_spec.ini @@ -0,0 +1,7 @@ +[plugin_spec] +# One of BICUBIC, BILINEAR, NEAREST, ANTIALIAS +resize_filter = string(default="ANTIALIAS") +#level of compression used when resizing images +quality = integer(default=90) + + diff --git a/mediagoblin/media_types/image/processing.py b/mediagoblin/media_types/image/processing.py index bc0ce3f8..1db82ee7 100644 --- a/mediagoblin/media_types/image/processing.py +++ b/mediagoblin/media_types/image/processing.py @@ -20,9 +20,14 @@ except ImportError: import Image import os import logging +import argparse from mediagoblin import mg_globals as mgg -from mediagoblin.processing import BadMediaFail, FilenameBuilder +from mediagoblin.processing import ( + BadMediaFail, FilenameBuilder, + MediaProcessor, ProcessingManager, + request_from_args, get_process_filename, + store_public, copy_original) from mediagoblin.tools.exif import exif_fix_image_orientation, \ extract_exif, clean_exif, get_gps_data, get_useful, \ exif_image_needs_rotation @@ -35,9 +40,11 @@ PIL_FILTERS = { 'BICUBIC': Image.BICUBIC, 'ANTIALIAS': Image.ANTIALIAS} +MEDIA_TYPE = 'mediagoblin.media_types.image' -def resize_image(proc_state, resized, keyname, target_name, new_size, - exif_tags, workdir): + +def resize_image(entry, resized, keyname, target_name, new_size, + exif_tags, workdir, quality, filter): """ Store a resized version of an image and return its pathname. @@ -49,17 +56,16 @@ def resize_image(proc_state, resized, keyname, target_name, new_size, exif_tags -- EXIF data for the original image workdir -- directory path for storing converted image files new_size -- 2-tuple size for the resized image + quality -- level of compression used when resizing images + filter -- One of BICUBIC, BILINEAR, NEAREST, ANTIALIAS """ - config = mgg.global_config['media_type:mediagoblin.media_types.image'] - resized = exif_fix_image_orientation(resized, exif_tags) # Fix orientation - filter_config = config['resize_filter'] try: - resize_filter = PIL_FILTERS[filter_config.upper()] + resize_filter = PIL_FILTERS[filter.upper()] except KeyError: raise Exception('Filter "{0}" not found, choose one of {1}'.format( - unicode(filter_config), + unicode(filter), u', '.join(PIL_FILTERS.keys()))) resized.thumbnail(new_size, resize_filter) @@ -67,102 +73,301 @@ def resize_image(proc_state, resized, keyname, target_name, new_size, # Copy the new file to the conversion subdir, then remotely. tmp_resized_filename = os.path.join(workdir, target_name) with file(tmp_resized_filename, 'w') as resized_file: - resized.save(resized_file, quality=config['quality']) - proc_state.store_public(keyname, tmp_resized_filename, target_name) + resized.save(resized_file, quality=quality) + store_public(entry, keyname, tmp_resized_filename, target_name) + + # store the thumb/medium info + image_info = {'width': new_size[0], + 'height': new_size[1], + 'quality': quality, + 'filter': filter} + + entry.set_file_metadata(keyname, **image_info) + + +def resize_tool(entry, + force, keyname, orig_file, target_name, + conversions_subdir, exif_tags, quality, filter, new_size=None): + # Use the default size if new_size was not given + if not new_size: + max_width = mgg.global_config['media:' + keyname]['max_width'] + max_height = mgg.global_config['media:' + keyname]['max_height'] + new_size = (max_width, max_height) + + # If thumb or medium is already the same quality and size, then don't + # reprocess + if _skip_resizing(entry, keyname, new_size, quality, filter): + _log.info('{0} of same size and quality already in use, skipping ' + 'resizing of media {1}.'.format(keyname, entry.id)) + return - -def resize_tool(proc_state, force, keyname, target_name, - conversions_subdir, exif_tags): - # filename -- the filename of the original image being resized - filename = proc_state.get_queued_filename() - max_width = mgg.global_config['media:' + keyname]['max_width'] - max_height = mgg.global_config['media:' + keyname]['max_height'] # If the size of the original file exceeds the specified size for the desized # file, a target_name file is created and later associated with the media # entry. # Also created if the file needs rotation, or if forced. try: - im = Image.open(filename) + im = Image.open(orig_file) except IOError: raise BadMediaFail() if force \ - or im.size[0] > max_width \ - or im.size[1] > max_height \ + or im.size[0] > new_size[0]\ + or im.size[1] > new_size[1]\ or exif_image_needs_rotation(exif_tags): resize_image( - proc_state, im, unicode(keyname), target_name, - (max_width, max_height), - exif_tags, conversions_subdir) - + entry, im, unicode(keyname), target_name, + tuple(new_size), + exif_tags, conversions_subdir, + quality, filter) -SUPPORTED_FILETYPES = ['png', 'gif', 'jpg', 'jpeg'] +def _skip_resizing(entry, keyname, size, quality, filter): + """ + Determines wither the saved thumb or medium is of the same quality and size + """ + image_info = entry.get_file_metadata(keyname) -def sniff_handler(media_file, **kw): - if kw.get('media') is not None: # That's a double negative! - name, ext = os.path.splitext(kw['media'].filename) - clean_ext = ext[1:].lower() # Strip the . from ext and make lowercase - - if clean_ext in SUPPORTED_FILETYPES: - _log.info('Found file extension in supported filetypes') - return True - else: - _log.debug('Media present, extension not found in {0}'.format( - SUPPORTED_FILETYPES)) - else: - _log.warning('Need additional information (keyword argument \'media\')' - ' to be able to handle sniffing') + if not image_info: + return False - return False + skip = True + if image_info.get('width') != size[0]: + skip = False -def process_image(proc_state): - """Code to process an image. Will be run by celery. + elif image_info.get('height') != size[1]: + skip = False - A Workbench() represents a local tempory dir. It is automatically - cleaned up when this function exits. - """ - entry = proc_state.entry - workbench = proc_state.workbench + elif image_info.get('filter') != filter: + skip = False - # Conversions subdirectory to avoid collisions - conversions_subdir = os.path.join( - workbench.dir, 'conversions') - os.mkdir(conversions_subdir) + elif image_info.get('quality') != quality: + skip = False - queued_filename = proc_state.get_queued_filename() - name_builder = FilenameBuilder(queued_filename) + return skip - # EXIF extraction - exif_tags = extract_exif(queued_filename) - gps_data = get_gps_data(exif_tags) - # Always create a small thumbnail - resize_tool(proc_state, True, 'thumb', - name_builder.fill('{basename}.thumbnail{ext}'), - conversions_subdir, exif_tags) +SUPPORTED_FILETYPES = ['png', 'gif', 'jpg', 'jpeg', 'tiff'] - # Possibly create a medium - resize_tool(proc_state, False, 'medium', - name_builder.fill('{basename}.medium{ext}'), - conversions_subdir, exif_tags) - # Copy our queued local workbench to its final destination - proc_state.copy_original(name_builder.fill('{basename}{ext}')) +def sniff_handler(media_file, filename): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) + name, ext = os.path.splitext(filename) + clean_ext = ext[1:].lower() # Strip the . from ext and make lowercase - # Remove queued media file from storage and database - proc_state.delete_queue_file() + if clean_ext in SUPPORTED_FILETYPES: + _log.info('Found file extension in supported filetypes') + return MEDIA_TYPE + else: + _log.debug('Media present, extension not found in {0}'.format( + SUPPORTED_FILETYPES)) - # Insert exif data into database - exif_all = clean_exif(exif_tags) + return None - if len(exif_all): - entry.media_data_init(exif_all=exif_all) - if len(gps_data): - for key in list(gps_data.keys()): - gps_data['gps_' + key] = gps_data.pop(key) - entry.media_data_init(**gps_data) +class CommonImageProcessor(MediaProcessor): + """ + Provides a base for various media processing steps + """ + # list of acceptable file keys in order of prefrence for reprocessing + acceptable_files = ['original', 'medium'] + + def common_setup(self): + """ + Set up the workbench directory and pull down the original file + """ + self.image_config = mgg.global_config['plugins'][ + 'mediagoblin.media_types.image'] + + ## @@: Should this be two functions? + # Conversions subdirectory to avoid collisions + self.conversions_subdir = os.path.join( + self.workbench.dir, 'conversions') + os.mkdir(self.conversions_subdir) + + # Pull down and set up the processing file + self.process_filename = get_process_filename( + self.entry, self.workbench, self.acceptable_files) + self.name_builder = FilenameBuilder(self.process_filename) + + # Exif extraction + self.exif_tags = extract_exif(self.process_filename) + + def generate_medium_if_applicable(self, size=None, quality=None, + filter=None): + if not quality: + quality = self.image_config['quality'] + if not filter: + filter = self.image_config['resize_filter'] + + resize_tool(self.entry, False, 'medium', self.process_filename, + self.name_builder.fill('{basename}.medium{ext}'), + self.conversions_subdir, self.exif_tags, quality, + filter, size) + + def generate_thumb(self, size=None, quality=None, filter=None): + if not quality: + quality = self.image_config['quality'] + if not filter: + filter = self.image_config['resize_filter'] + + resize_tool(self.entry, True, 'thumb', self.process_filename, + self.name_builder.fill('{basename}.thumbnail{ext}'), + self.conversions_subdir, self.exif_tags, quality, + filter, size) + + def copy_original(self): + copy_original( + self.entry, self.process_filename, + self.name_builder.fill('{basename}{ext}')) + + def extract_metadata(self): + # Is there any GPS data + gps_data = get_gps_data(self.exif_tags) + + # Insert exif data into database + exif_all = clean_exif(self.exif_tags) + + if len(exif_all): + self.entry.media_data_init(exif_all=exif_all) + + if len(gps_data): + for key in list(gps_data.keys()): + gps_data['gps_' + key] = gps_data.pop(key) + self.entry.media_data_init(**gps_data) + + +class InitialProcessor(CommonImageProcessor): + """ + Initial processing step for new images + """ + name = "initial" + description = "Initial processing" + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + """ + Determine if this media type is eligible for processing + """ + if not state: + state = entry.state + return state in ( + "unprocessed", "failed") + + ############################### + # Command line interface things + ############################### + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + parser.add_argument( + '--thumb-size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + parser.add_argument( + '--filter', + choices=['BICUBIC', 'BILINEAR', 'NEAREST', 'ANTIALIAS']) + + parser.add_argument( + '--quality', + type=int, + help='level of compression used when resizing images') + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['size', 'thumb_size', 'filter', 'quality']) + + def process(self, size=None, thumb_size=None, quality=None, filter=None): + self.common_setup() + self.generate_medium_if_applicable(size=size, filter=filter, + quality=quality) + self.generate_thumb(size=thumb_size, filter=filter, quality=quality) + self.copy_original() + self.extract_metadata() + self.delete_queue_file() + + +class Resizer(CommonImageProcessor): + """ + Resizing process steps for processed media + """ + name = 'resize' + description = 'Resize image' + thumb_size = 'size' + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + """ + Determine if this media type is eligible for processing + """ + if not state: + state = entry.state + return state in 'processed' + + ############################### + # Command line interface things + ############################### + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + parser.add_argument( + '--filter', + choices=['BICUBIC', 'BILINEAR', 'NEAREST', 'ANTIALIAS']) + + parser.add_argument( + '--quality', + type=int, + help='level of compression used when resizing images') + + parser.add_argument( + 'file', + choices=['medium', 'thumb']) + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['size', 'file', 'quality', 'filter']) + + def process(self, file, size=None, filter=None, quality=None): + self.common_setup() + if file == 'medium': + self.generate_medium_if_applicable(size=size, filter=filter, + quality=quality) + elif file == 'thumb': + self.generate_thumb(size=size, filter=filter, quality=quality) + + +class ImageProcessingManager(ProcessingManager): + def __init__(self): + super(self.__class__, self).__init__() + self.add_processor(InitialProcessor) + self.add_processor(Resizer) if __name__ == '__main__': diff --git a/mediagoblin/media_types/pdf/__init__.py b/mediagoblin/media_types/pdf/__init__.py index a6d23c93..de70389e 100644 --- a/mediagoblin/media_types/pdf/__init__.py +++ b/mediagoblin/media_types/pdf/__init__.py @@ -14,16 +14,29 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from mediagoblin.media_types.pdf.processing import process_pdf, \ +from mediagoblin.media_types import MediaManagerBase +from mediagoblin.media_types.pdf.processing import PdfProcessingManager, \ sniff_handler -MEDIA_MANAGER = { - "human_readable": "PDF", - "processor": process_pdf, # alternately a string, - # 'mediagoblin.media_types.image.processing'? - "sniff_handler": sniff_handler, - "display_template": "mediagoblin/media_displays/pdf.html", - "default_thumb": "images/media_thumbs/pdf.jpg", - "accepted_extensions": [ - "pdf"]} +ACCEPTED_EXTENSIONS = ['pdf'] +MEDIA_TYPE = 'mediagoblin.media_types.pdf' + + +class PDFMediaManager(MediaManagerBase): + human_readable = "PDF" + display_template = "mediagoblin/media_displays/pdf.html" + default_thumb = "images/media_thumbs/pdf.jpg" + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, PDFMediaManager + + +hooks = { + 'get_media_type_and_manager': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + ('media_manager', MEDIA_TYPE): lambda: PDFMediaManager, + ('reprocess_manager', MEDIA_TYPE): lambda: PdfProcessingManager, +} diff --git a/mediagoblin/media_types/pdf/config_spec.ini b/mediagoblin/media_types/pdf/config_spec.ini new file mode 100644 index 00000000..c8a12cba --- /dev/null +++ b/mediagoblin/media_types/pdf/config_spec.ini @@ -0,0 +1,5 @@ +[plugin_spec] +pdf_js = boolean(default=True) + + + diff --git a/mediagoblin/media_types/pdf/processing.py b/mediagoblin/media_types/pdf/processing.py index 49742fd7..a000007a 100644 --- a/mediagoblin/media_types/pdf/processing.py +++ b/mediagoblin/media_types/pdf/processing.py @@ -13,18 +13,24 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import argparse import os import logging import dateutil.parser from subprocess import PIPE, Popen from mediagoblin import mg_globals as mgg -from mediagoblin.processing import (create_pub_filepath, - FilenameBuilder, BadMediaFail) +from mediagoblin.processing import ( + FilenameBuilder, BadMediaFail, + MediaProcessor, ProcessingManager, + request_from_args, get_process_filename, + store_public, copy_original) from mediagoblin.tools.translate import fake_ugettext_passthrough as _ _log = logging.getLogger(__name__) +MEDIA_TYPE = 'mediagoblin.media_types.pdf' + # TODO - cache (memoize) util # This is a list created via uniconv --show and hand removing some types that @@ -162,17 +168,16 @@ def check_prerequisites(): return False return True -def sniff_handler(media_file, **kw): +def sniff_handler(media_file, filename): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) if not check_prerequisites(): - return False - if kw.get('media') is not None: - name, ext = os.path.splitext(kw['media'].filename) - clean_ext = ext[1:].lower() + return None - if clean_ext in supported_extensions(): - return True + name, ext = os.path.splitext(filename) + clean_ext = ext[1:].lower() - return False + if clean_ext in supported_extensions(): + return MEDIA_TYPE def create_pdf_thumb(original, thumb_filename, width, height): # Note: pdftocairo adds '.png', remove it @@ -205,6 +210,11 @@ def pdf_info(original): info_dict = dict([[part.strip() for part in l.strip().split(':', 1)] for l in lines if ':' in l]) + if 'Page size' not in info_dict.keys(): + # TODO - message is for the user, not debug, but BadMediaFail not taking an argument, fix that. + _log.debug('Missing "Page size" key in returned pdf - conversion failed?') + raise BadMediaFail() + for date_key in [('pdf_mod_date', 'ModDate'), ('pdf_creation_date', 'CreationDate')]: if date_key in info_dict: @@ -227,51 +237,235 @@ def pdf_info(original): return ret_dict -def process_pdf(proc_state): - """Code to process a pdf file. Will be run by celery. - A Workbench() represents a local tempory dir. It is automatically - cleaned up when this function exits. +class CommonPdfProcessor(MediaProcessor): """ - entry = proc_state.entry - workbench = proc_state.workbench - - queued_filename = proc_state.get_queued_filename() - name_builder = FilenameBuilder(queued_filename) - - # Copy our queued local workbench to its final destination - original_dest = name_builder.fill('{basename}{ext}') - proc_state.copy_original(original_dest) - - # Create a pdf if this is a different doc, store pdf for viewer - ext = queued_filename.rsplit('.', 1)[-1].lower() - if ext == 'pdf': - pdf_filename = queued_filename - else: - pdf_filename = queued_filename.rsplit('.', 1)[0] + '.pdf' + Provides a base for various pdf processing steps + """ + acceptable_files = ['original', 'pdf'] + + def common_setup(self): + """ + Set up common pdf processing steps + """ + # Pull down and set up the processing file + self.process_filename = get_process_filename( + self.entry, self.workbench, self.acceptable_files) + self.name_builder = FilenameBuilder(self.process_filename) + + self._set_pdf_filename() + + def _set_pdf_filename(self): + if self.name_builder.ext == '.pdf': + self.pdf_filename = self.process_filename + elif self.entry.media_files.get('pdf'): + self.pdf_filename = self.workbench.localized_file( + mgg.public_store, self.entry.media_files['pdf']) + else: + self.pdf_filename = self._generate_pdf() + + def _skip_processing(self, keyname, **kwargs): + file_metadata = self.entry.get_file_metadata(keyname) + skip = True + + if not file_metadata: + return False + + if keyname == 'thumb': + if kwargs.get('thumb_size') != file_metadata.get('thumb_size'): + skip = False + elif keyname == 'medium': + if kwargs.get('size') != file_metadata.get('size'): + skip = False + + return skip + + def copy_original(self): + copy_original( + self.entry, self.process_filename, + self.name_builder.fill('{basename}{ext}')) + + def generate_thumb(self, thumb_size=None): + if not thumb_size: + thumb_size = (mgg.global_config['media:thumb']['max_width'], + mgg.global_config['media:thumb']['max_height']) + + if self._skip_processing('thumb', thumb_size=thumb_size): + return + + # Note: pdftocairo adds '.png', so don't include an ext + thumb_filename = os.path.join(self.workbench.dir, + self.name_builder.fill( + '{basename}.thumbnail')) + + executable = where('pdftocairo') + args = [executable, '-scale-to', str(min(thumb_size)), + '-singlefile', '-png', self.pdf_filename, thumb_filename] + + _log.debug('calling {0}'.format(repr(' '.join(args)))) + Popen(executable=executable, args=args).wait() + + # since pdftocairo added '.png', we need to include it with the + # filename + store_public(self.entry, 'thumb', thumb_filename + '.png', + self.name_builder.fill('{basename}.thumbnail.png')) + + self.entry.set_file_metadata('thumb', thumb_size=thumb_size) + + def _generate_pdf(self): + """ + Store the pdf. If the file is not a pdf, make it a pdf + """ + tmp_pdf = os.path.splitext(self.process_filename)[0] + '.pdf' + unoconv = where('unoconv') - call(executable=unoconv, - args=[unoconv, '-v', '-f', 'pdf', queued_filename]) - if not os.path.exists(pdf_filename): + args = [unoconv, '-v', '-f', 'pdf', self.process_filename] + _log.debug('calling %s' % repr(args)) + Popen(executable=unoconv, + args=args).wait() + + if not os.path.exists(tmp_pdf): _log.debug('unoconv failed to convert file to pdf') raise BadMediaFail() - proc_state.store_public(keyname=u'pdf', local_file=pdf_filename) - - pdf_info_dict = pdf_info(pdf_filename) - - for name, width, height in [ - (u'thumb', mgg.global_config['media:thumb']['max_width'], - mgg.global_config['media:thumb']['max_height']), - (u'medium', mgg.global_config['media:medium']['max_width'], - mgg.global_config['media:medium']['max_height']), - ]: - filename = name_builder.fill('{basename}.%s.png' % name) - path = workbench.joinpath(filename) - create_pdf_thumb(pdf_filename, path, width, height) - assert(os.path.exists(path)) - proc_state.store_public(keyname=name, local_file=path) - - proc_state.delete_queue_file() - - entry.media_data_init(**pdf_info_dict) - entry.save() + + store_public(self.entry, 'pdf', tmp_pdf, + self.name_builder.fill('{basename}.pdf')) + + return self.workbench.localized_file( + mgg.public_store, self.entry.media_files['pdf']) + + def extract_pdf_info(self): + pdf_info_dict = pdf_info(self.pdf_filename) + self.entry.media_data_init(**pdf_info_dict) + + def generate_medium(self, size=None): + if not size: + size = (mgg.global_config['media:medium']['max_width'], + mgg.global_config['media:medium']['max_height']) + + if self._skip_processing('medium', size=size): + return + + # Note: pdftocairo adds '.png', so don't include an ext + filename = os.path.join(self.workbench.dir, + self.name_builder.fill('{basename}.medium')) + + executable = where('pdftocairo') + args = [executable, '-scale-to', str(min(size)), + '-singlefile', '-png', self.pdf_filename, filename] + + _log.debug('calling {0}'.format(repr(' '.join(args)))) + Popen(executable=executable, args=args).wait() + + # since pdftocairo added '.png', we need to include it with the + # filename + store_public(self.entry, 'medium', filename + '.png', + self.name_builder.fill('{basename}.medium.png')) + + self.entry.set_file_metadata('medium', size=size) + + +class InitialProcessor(CommonPdfProcessor): + """ + Initial processing step for new pdfs + """ + name = "initial" + description = "Initial processing" + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + """ + Determine if this media type is eligible for processing + """ + if not state: + state = entry.state + return state in ( + "unprocessed", "failed") + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + parser.add_argument( + '--thumb-size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['size', 'thumb_size']) + + def process(self, size=None, thumb_size=None): + self.common_setup() + self.extract_pdf_info() + self.copy_original() + self.generate_medium(size=size) + self.generate_thumb(thumb_size=thumb_size) + self.delete_queue_file() + + +class Resizer(CommonPdfProcessor): + """ + Resizing process steps for processed pdfs + """ + name = 'resize' + description = 'Resize thumbnail and medium' + thumb_size = 'size' + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + """ + Determine if this media type is eligible for processing + """ + if not state: + state = entry.state + return state in 'processed' + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + parser.add_argument( + 'file', + choices=['medium', 'thumb']) + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['size', 'file']) + + def process(self, file, size=None): + self.common_setup() + if file == 'medium': + self.generate_medium(size=size) + elif file == 'thumb': + self.generate_thumb(thumb_size=size) + + +class PdfProcessingManager(ProcessingManager): + def __init__(self): + super(self.__class__, self).__init__() + self.add_processor(InitialProcessor) + self.add_processor(Resizer) diff --git a/mediagoblin/media_types/stl/__init__.py b/mediagoblin/media_types/stl/__init__.py index edffc633..d5b56b4b 100644 --- a/mediagoblin/media_types/stl/__init__.py +++ b/mediagoblin/media_types/stl/__init__.py @@ -14,14 +14,28 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from mediagoblin.media_types.stl.processing import process_stl, \ +from mediagoblin.media_types import MediaManagerBase +from mediagoblin.media_types.stl.processing import StlProcessingManager, \ sniff_handler -MEDIA_MANAGER = { - "human_readable": "stereo lithographics", - "processor": process_stl, - "sniff_handler": sniff_handler, - "display_template": "mediagoblin/media_displays/stl.html", - "default_thumb": "images/media_thumbs/video.jpg", - "accepted_extensions": ["obj", "stl"]} +MEDIA_TYPE = 'mediagoblin.media_types.stl' +ACCEPTED_EXTENSIONS = ["obj", "stl"] + + +class STLMediaManager(MediaManagerBase): + human_readable = "stereo lithographics" + display_template = "mediagoblin/media_displays/stl.html" + default_thumb = "images/media_thumbs/video.jpg" + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, STLMediaManager + +hooks = { + 'get_media_type_and_manager': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + ('media_manager', MEDIA_TYPE): lambda: STLMediaManager, + ('reprocess_manager', MEDIA_TYPE): lambda: StlProcessingManager, +} diff --git a/mediagoblin/media_types/stl/processing.py b/mediagoblin/media_types/stl/processing.py index 49382495..65a86234 100644 --- a/mediagoblin/media_types/stl/processing.py +++ b/mediagoblin/media_types/stl/processing.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import argparse import os import json import logging @@ -21,14 +22,18 @@ import subprocess import pkg_resources from mediagoblin import mg_globals as mgg -from mediagoblin.processing import create_pub_filepath, \ - FilenameBuilder +from mediagoblin.processing import ( + FilenameBuilder, MediaProcessor, + ProcessingManager, request_from_args, + get_process_filename, store_public, + copy_original) from mediagoblin.media_types.stl import model_loader _log = logging.getLogger(__name__) SUPPORTED_FILETYPES = ['stl', 'obj'] +MEDIA_TYPE = 'mediagoblin.media_types.stl' BLEND_FILE = pkg_resources.resource_filename( 'mediagoblin.media_types.stl', @@ -42,22 +47,20 @@ BLEND_SCRIPT = pkg_resources.resource_filename( 'blender_render.py')) -def sniff_handler(media_file, **kw): - if kw.get('media') is not None: - name, ext = os.path.splitext(kw['media'].filename) - clean_ext = ext[1:].lower() - - if clean_ext in SUPPORTED_FILETYPES: - _log.info('Found file extension in supported filetypes') - return True - else: - _log.debug('Media present, extension not found in {0}'.format( - SUPPORTED_FILETYPES)) +def sniff_handler(media_file, filename): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) + + name, ext = os.path.splitext(filename) + clean_ext = ext[1:].lower() + + if clean_ext in SUPPORTED_FILETYPES: + _log.info('Found file extension in supported filetypes') + return MEDIA_TYPE else: - _log.warning('Need additional information (keyword argument \'media\')' - ' to be able to handle sniffing') + _log.debug('Media present, extension not found in {0}'.format( + SUPPORTED_FILETYPES)) - return False + return None def blender_render(config): @@ -73,49 +76,61 @@ def blender_render(config): env=env) -def process_stl(proc_state): - """Code to process an stl or obj model. Will be run by celery. - - A Workbench() represents a local tempory dir. It is automatically - cleaned up when this function exits. +class CommonStlProcessor(MediaProcessor): """ - entry = proc_state.entry - workbench = proc_state.workbench - - queued_filepath = entry.queued_media_file - queued_filename = workbench.localized_file( - mgg.queue_store, queued_filepath, 'source') - name_builder = FilenameBuilder(queued_filename) - - ext = queued_filename.lower().strip()[-4:] - if ext.startswith("."): - ext = ext[1:] - else: - ext = None - - # Attempt to parse the model file and divine some useful - # information about it. - with open(queued_filename, 'rb') as model_file: - model = model_loader.auto_detect(model_file, ext) - - # generate preview images - greatest = [model.width, model.height, model.depth] - greatest.sort() - greatest = greatest[-1] - - def snap(name, camera, width=640, height=640, project="ORTHO"): - filename = name_builder.fill(name) - workbench_path = workbench.joinpath(filename) + Provides a common base for various stl processing steps + """ + acceptable_files = ['original'] + + def common_setup(self): + # Pull down and set up the processing file + self.process_filename = get_process_filename( + self.entry, self.workbench, self.acceptable_files) + self.name_builder = FilenameBuilder(self.process_filename) + + self._set_ext() + self._set_model() + self._set_greatest() + + def _set_ext(self): + ext = self.name_builder.ext[1:] + + if not ext: + ext = None + + self.ext = ext + + def _set_model(self): + """ + Attempt to parse the model file and divine some useful + information about it. + """ + with open(self.process_filename, 'rb') as model_file: + self.model = model_loader.auto_detect(model_file, self.ext) + + def _set_greatest(self): + greatest = [self.model.width, self.model.height, self.model.depth] + greatest.sort() + self.greatest = greatest[-1] + + def copy_original(self): + copy_original( + self.entry, self.process_filename, + self.name_builder.fill('{basename}{ext}')) + + def _snap(self, keyname, name, camera, size, project="ORTHO"): + filename = self.name_builder.fill(name) + workbench_path = self.workbench.joinpath(filename) shot = { - "model_path": queued_filename, - "model_ext": ext, + "model_path": self.process_filename, + "model_ext": self.ext, "camera_coord": camera, - "camera_focus": model.average, - "camera_clip": greatest*10, - "greatest": greatest, + "camera_focus": self.model.average, + "camera_clip": self.greatest*10, + "greatest": self.greatest, "projection": project, - "width": width, - "height": height, + "width": size[0], + "height": size[1], "out_file": workbench_path, } blender_render(shot) @@ -124,70 +139,232 @@ def process_stl(proc_state): assert os.path.exists(workbench_path) # copy it up! - with open(workbench_path, 'rb') as rendered_file: - public_path = create_pub_filepath(entry, filename) - - with mgg.public_store.get_file(public_path, "wb") as public_file: - public_file.write(rendered_file.read()) - - return public_path - - thumb_path = snap( - "{basename}.thumb.jpg", - [0, greatest*-1.5, greatest], - mgg.global_config['media:thumb']['max_width'], - mgg.global_config['media:thumb']['max_height'], - project="PERSP") - - perspective_path = snap( - "{basename}.perspective.jpg", - [0, greatest*-1.5, greatest], project="PERSP") - - topview_path = snap( - "{basename}.top.jpg", - [model.average[0], model.average[1], greatest*2]) - - frontview_path = snap( - "{basename}.front.jpg", - [model.average[0], greatest*-2, model.average[2]]) - - sideview_path = snap( - "{basename}.side.jpg", - [greatest*-2, model.average[1], model.average[2]]) - - ## Save the public file stuffs - model_filepath = create_pub_filepath( - entry, name_builder.fill('{basename}{ext}')) - - with mgg.public_store.get_file(model_filepath, 'wb') as model_file: - with open(queued_filename, 'rb') as queued_file: - model_file.write(queued_file.read()) - - # Remove queued media file from storage and database. - # queued_filepath is in the task_id directory which should - # be removed too, but fail if the directory is not empty to be on - # the super-safe side. - mgg.queue_store.delete_file(queued_filepath) # rm file - mgg.queue_store.delete_dir(queued_filepath[:-1]) # rm dir - entry.queued_media_file = [] - - # Insert media file information into database - media_files_dict = entry.setdefault('media_files', {}) - media_files_dict[u'original'] = model_filepath - media_files_dict[u'thumb'] = thumb_path - media_files_dict[u'perspective'] = perspective_path - media_files_dict[u'top'] = topview_path - media_files_dict[u'side'] = sideview_path - media_files_dict[u'front'] = frontview_path - - # Put model dimensions into the database - dimensions = { - "center_x" : model.average[0], - "center_y" : model.average[1], - "center_z" : model.average[2], - "width" : model.width, - "height" : model.height, - "depth" : model.depth, - "file_type" : ext, - } - entry.media_data_init(**dimensions) + store_public(self.entry, keyname, workbench_path, filename) + + def _skip_processing(self, keyname, **kwargs): + file_metadata = self.entry.get_file_metadata(keyname) + + if not file_metadata: + return False + skip = True + + if keyname == 'thumb': + if kwargs.get('thumb_size') != file_metadata.get('thumb_size'): + skip = False + else: + if kwargs.get('size') != file_metadata.get('size'): + skip = False + + return skip + + def generate_thumb(self, thumb_size=None): + if not thumb_size: + thumb_size = (mgg.global_config['media:thumb']['max_width'], + mgg.global_config['media:thumb']['max_height']) + + if self._skip_processing('thumb', thumb_size=thumb_size): + return + + self._snap( + "thumb", + "{basename}.thumb.jpg", + [0, self.greatest*-1.5, self.greatest], + thumb_size, + project="PERSP") + + self.entry.set_file_metadata('thumb', thumb_size=thumb_size) + + def generate_perspective(self, size=None): + if not size: + size = (mgg.global_config['media:medium']['max_width'], + mgg.global_config['media:medium']['max_height']) + + if self._skip_processing('perspective', size=size): + return + + self._snap( + "perspective", + "{basename}.perspective.jpg", + [0, self.greatest*-1.5, self.greatest], + size, + project="PERSP") + + self.entry.set_file_metadata('perspective', size=size) + + def generate_topview(self, size=None): + if not size: + size = (mgg.global_config['media:medium']['max_width'], + mgg.global_config['media:medium']['max_height']) + + if self._skip_processing('top', size=size): + return + + self._snap( + "top", + "{basename}.top.jpg", + [self.model.average[0], self.model.average[1], + self.greatest*2], + size) + + self.entry.set_file_metadata('top', size=size) + + def generate_frontview(self, size=None): + if not size: + size = (mgg.global_config['media:medium']['max_width'], + mgg.global_config['media:medium']['max_height']) + + if self._skip_processing('front', size=size): + return + + self._snap( + "front", + "{basename}.front.jpg", + [self.model.average[0], self.greatest*-2, + self.model.average[2]], + size) + + self.entry.set_file_metadata('front', size=size) + + def generate_sideview(self, size=None): + if not size: + size = (mgg.global_config['media:medium']['max_width'], + mgg.global_config['media:medium']['max_height']) + + if self._skip_processing('side', size=size): + return + + self._snap( + "side", + "{basename}.side.jpg", + [self.greatest*-2, self.model.average[1], + self.model.average[2]], + size) + + self.entry.set_file_metadata('side', size=size) + + def store_dimensions(self): + """ + Put model dimensions into the database + """ + dimensions = { + "center_x": self.model.average[0], + "center_y": self.model.average[1], + "center_z": self.model.average[2], + "width": self.model.width, + "height": self.model.height, + "depth": self.model.depth, + "file_type": self.ext, + } + self.entry.media_data_init(**dimensions) + + +class InitialProcessor(CommonStlProcessor): + """ + Initial processing step for new stls + """ + name = "initial" + description = "Initial processing" + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + """ + Determine if this media type is eligible for processing + """ + if not state: + state = entry.state + return state in ( + "unprocessed", "failed") + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + parser.add_argument( + '--thumb_size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['size', 'thumb_size']) + + def process(self, size=None, thumb_size=None): + self.common_setup() + self.generate_thumb(thumb_size=thumb_size) + self.generate_perspective(size=size) + self.generate_topview(size=size) + self.generate_frontview(size=size) + self.generate_sideview(size=size) + self.store_dimensions() + self.copy_original() + self.delete_queue_file() + + +class Resizer(CommonStlProcessor): + """ + Resizing process steps for processed stls + """ + name = 'resize' + description = 'Resize thumbnail and mediums' + thumb_size = 'size' + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + """ + Determine if this media type is eligible for processing + """ + if not state: + state = entry.state + return state in 'processed' + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + parser.add_argument( + 'file', + choices=['medium', 'thumb']) + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['size', 'file']) + + def process(self, file, size=None): + self.common_setup() + if file == 'medium': + self.generate_perspective(size=size) + self.generate_topview(size=size) + self.generate_frontview(size=size) + self.generate_sideview(size=size) + elif file == 'thumb': + self.generate_thumb(thumb_size=size) + + +class StlProcessingManager(ProcessingManager): + def __init__(self): + super(self.__class__, self).__init__() + self.add_processor(InitialProcessor) + self.add_processor(Resizer) diff --git a/mediagoblin/media_types/tools.py b/mediagoblin/media_types/tools.py new file mode 100644 index 00000000..fe7b3772 --- /dev/null +++ b/mediagoblin/media_types/tools.py @@ -0,0 +1,27 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import logging + +from mediagoblin import mg_globals + +_log = logging.getLogger(__name__) + + +def media_type_warning(): + if mg_globals.app_config.get('media_types'): + _log.warning('Media_types have been converted to plugins. Old' + ' media_types will no longer work. Please convert them' + ' to plugins to continue using them.') diff --git a/mediagoblin/media_types/video/__init__.py b/mediagoblin/media_types/video/__init__.py index fab601f6..c85cc0b2 100644 --- a/mediagoblin/media_types/video/__init__.py +++ b/mediagoblin/media_types/video/__init__.py @@ -14,21 +14,33 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from mediagoblin.media_types.video.processing import process_video, \ +from mediagoblin.media_types import MediaManagerBase +from mediagoblin.media_types.video.processing import VideoProcessingManager, \ sniff_handler -MEDIA_MANAGER = { - "human_readable": "Video", - "processor": process_video, # alternately a string, - # 'mediagoblin.media_types.image.processing'? - "sniff_handler": sniff_handler, - "display_template": "mediagoblin/media_displays/video.html", - "default_thumb": "images/media_thumbs/video.jpg", - "accepted_extensions": [ - "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "m4v"], +MEDIA_TYPE = 'mediagoblin.media_types.video' +ACCEPTED_EXTENSIONS = [ + "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "m4v"] + + +class VideoMediaManager(MediaManagerBase): + human_readable = "Video" + display_template = "mediagoblin/media_displays/video.html" + default_thumb = "images/media_thumbs/video.jpg" # Used by the media_entry.get_display_media method - "media_fetch_order": [u'webm_640', u'original'], - "default_webm_type": 'video/webm; codecs="vp8, vorbis"', + media_fetch_order = [u'webm_video', u'original'] + default_webm_type = 'video/webm; codecs="vp8, vorbis"' + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, VideoMediaManager + +hooks = { + 'get_media_type_and_manager': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + ('media_manager', MEDIA_TYPE): lambda: VideoMediaManager, + ('reprocess_manager', MEDIA_TYPE): lambda: VideoProcessingManager, } diff --git a/mediagoblin/media_types/video/config_spec.ini b/mediagoblin/media_types/video/config_spec.ini new file mode 100644 index 00000000..98714f56 --- /dev/null +++ b/mediagoblin/media_types/video/config_spec.ini @@ -0,0 +1,22 @@ +[plugin_spec] +# Should we keep the original file? +keep_original = boolean(default=False) + +# 0 means autodetect, autodetect means number_of_CPUs - 1 +vp8_threads = integer(default=0) +# Range: 0..10 +vp8_quality = integer(default=8) +# Range: -0.1..1 +vorbis_quality = float(default=0.3) + +# Autoplay the video when page is loaded? +auto_play = boolean(default=False) + +[[skip_transcode]] +mime_types = string_list(default=list("video/webm")) +container_formats = string_list(default=list("Matroska")) +video_codecs = string_list(default=list("VP8 video")) +audio_codecs = string_list(default=list("Vorbis")) +dimensions_match = boolean(default=True) + + diff --git a/mediagoblin/media_types/video/migrations.py b/mediagoblin/media_types/video/migrations.py index 442bbd8d..d68e2933 100644 --- a/mediagoblin/media_types/video/migrations.py +++ b/mediagoblin/media_types/video/migrations.py @@ -20,6 +20,7 @@ from sqlalchemy import MetaData, Column, Unicode MIGRATIONS = {} + @RegisterMigration(1, MIGRATIONS) def add_orig_metadata_column(db_conn): metadata = MetaData(bind=db_conn.bind) @@ -30,3 +31,19 @@ def add_orig_metadata_column(db_conn): default=None, nullable=True) col.create(vid_data) db_conn.commit() + + +@RegisterMigration(2, MIGRATIONS) +def webm_640_to_webm_video(db): + metadata = MetaData(bind=db.bind) + + file_keynames = inspect_table(metadata, 'core__file_keynames') + + for row in db.execute(file_keynames.select()): + if row.name == 'webm_640': + db.execute( + file_keynames.update(). \ + where(file_keynames.c.id==row.id).\ + values(name='webm_video')) + + db.commit() diff --git a/mediagoblin/media_types/video/models.py b/mediagoblin/media_types/video/models.py index f696a892..be9d258f 100644 --- a/mediagoblin/media_types/video/models.py +++ b/mediagoblin/media_types/video/models.py @@ -36,12 +36,12 @@ class VideoData(Base): - orig_metadata: A loose json structure containing metadata gstreamer pulled from the original video. This field is NOT GUARANTEED to exist! - + Likely metadata extracted: "videoheight", "videolength", "videowidth", "audiorate", "audiolength", "audiochannels", "audiowidth", "mimetype", "tags" - + TODO: document the above better. """ __tablename__ = "video__mediadata" @@ -68,7 +68,7 @@ class VideoData(Base): """ orig_metadata = self.orig_metadata or {} - if "webm_640" not in self.get_media_entry.media_files \ + if "webm_video" not in self.get_media_entry.media_files \ and "mimetype" in orig_metadata \ and "tags" in orig_metadata \ and "audio-codec" in orig_metadata["tags"] \ @@ -90,7 +90,7 @@ class VideoData(Base): return '%s; codecs="%s, %s"' % ( mimetype, video_codec, audio_codec) else: - return video.MEDIA_MANAGER["default_webm_type"] + return video.VideoMediaManager.default_webm_type DATA_MODEL = VideoData diff --git a/mediagoblin/media_types/video/processing.py b/mediagoblin/media_types/video/processing.py index ff2c94a0..abd5f36e 100644 --- a/mediagoblin/media_types/video/processing.py +++ b/mediagoblin/media_types/video/processing.py @@ -14,13 +14,18 @@ # 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 tempfile import NamedTemporaryFile +import argparse +import os.path import logging import datetime from mediagoblin import mg_globals as mgg -from mediagoblin.processing import \ - create_pub_filepath, FilenameBuilder, BaseProcessingFail, ProgressCallback +from mediagoblin.processing import ( + FilenameBuilder, BaseProcessingFail, + ProgressCallback, MediaProcessor, + ProcessingManager, request_from_args, + get_process_filename, store_public, + copy_original) from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from . import transcoders @@ -29,6 +34,8 @@ from .util import skip_transcode _log = logging.getLogger(__name__) _log.setLevel(logging.DEBUG) +MEDIA_TYPE = 'mediagoblin.media_types.video' + class VideoTranscodingFail(BaseProcessingFail): ''' @@ -37,123 +44,21 @@ class VideoTranscodingFail(BaseProcessingFail): general_message = _(u'Video transcoding failed') -def sniff_handler(media_file, **kw): +def sniff_handler(media_file, filename): transcoder = transcoders.VideoTranscoder() data = transcoder.discover(media_file.name) + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) _log.debug('Discovered: {0}'.format(data)) if not data: - _log.error('Could not discover {0}'.format( - kw.get('media'))) - return False - - if data['is_video'] == True: - return True - - return False - - -def process_video(proc_state): - """ - Process a video entry, transcode the queued media files (originals) and - create a thumbnail for the entry. - - A Workbench() represents a local tempory dir. It is automatically - cleaned up when this function exits. - """ - entry = proc_state.entry - workbench = proc_state.workbench - video_config = mgg.global_config['media_type:mediagoblin.media_types.video'] - - queued_filepath = entry.queued_media_file - queued_filename = proc_state.get_queued_filename() - name_builder = FilenameBuilder(queued_filename) - - medium_filepath = create_pub_filepath( - entry, name_builder.fill('{basename}-640p.webm')) - - thumbnail_filepath = create_pub_filepath( - entry, name_builder.fill('{basename}.thumbnail.jpg')) - - # Create a temporary file for the video destination (cleaned up with workbench) - tmp_dst = NamedTemporaryFile(dir=workbench.dir, delete=False) - with tmp_dst: - # Transcode queued file to a VP8/vorbis file that fits in a 640x640 square - progress_callback = ProgressCallback(entry) - - dimensions = ( - mgg.global_config['media:medium']['max_width'], - mgg.global_config['media:medium']['max_height']) - - # Extract metadata and keep a record of it - metadata = transcoders.VideoTranscoder().discover(queued_filename) - store_metadata(entry, metadata) - - # Figure out whether or not we need to transcode this video or - # if we can skip it - if skip_transcode(metadata): - _log.debug('Skipping transcoding') - - dst_dimensions = metadata['videowidth'], metadata['videoheight'] - - # Push original file to public storage - _log.debug('Saving original...') - proc_state.copy_original(queued_filepath[-1]) + _log.error('Could not discover {0}'.format(filename)) + return None - did_transcode = False - else: - transcoder = transcoders.VideoTranscoder() - - transcoder.transcode(queued_filename, tmp_dst.name, - vp8_quality=video_config['vp8_quality'], - vp8_threads=video_config['vp8_threads'], - vorbis_quality=video_config['vorbis_quality'], - progress_callback=progress_callback, - dimensions=dimensions) - - dst_dimensions = transcoder.dst_data.videowidth,\ - transcoder.dst_data.videoheight - - # Push transcoded video to public storage - _log.debug('Saving medium...') - mgg.public_store.copy_local_to_storage(tmp_dst.name, medium_filepath) - _log.debug('Saved medium') - - entry.media_files['webm_640'] = medium_filepath - - did_transcode = True - - # Save the width and height of the transcoded video - entry.media_data_init( - width=dst_dimensions[0], - height=dst_dimensions[1]) - - # Temporary file for the video thumbnail (cleaned up with workbench) - tmp_thumb = NamedTemporaryFile(dir=workbench.dir, suffix='.jpg', delete=False) + if data['is_video'] is True: + return MEDIA_TYPE - with tmp_thumb: - # Create a thumbnail.jpg that fits in a 180x180 square - transcoders.VideoThumbnailerMarkII( - queued_filename, - tmp_thumb.name, - 180) - - # Push the thumbnail to public storage - _log.debug('Saving thumbnail...') - mgg.public_store.copy_local_to_storage(tmp_thumb.name, thumbnail_filepath) - entry.media_files['thumb'] = thumbnail_filepath - - # save the original... but only if we did a transcoding - # (if we skipped transcoding and just kept the original anyway as the main - # media, then why would we save the original twice?) - if video_config['keep_original'] and did_transcode: - # Push original file to public storage - _log.debug('Saving original...') - proc_state.copy_original(queued_filepath[-1]) - - # Remove queued media file from storage and database - proc_state.delete_queue_file() + return None def store_metadata(media_entry, metadata): @@ -164,9 +69,9 @@ def store_metadata(media_entry, metadata): stored_metadata = dict( [(key, metadata[key]) for key in [ - "videoheight", "videolength", "videowidth", - "audiorate", "audiolength", "audiochannels", "audiowidth", - "mimetype"] + "videoheight", "videolength", "videowidth", + "audiorate", "audiolength", "audiochannels", "audiowidth", + "mimetype"] if key in metadata]) # We have to convert videorate into a sequence because it's a @@ -185,10 +90,10 @@ def store_metadata(media_entry, metadata): tags = dict( [(key, tags_metadata[key]) for key in [ - "application-name", "artist", "audio-codec", "bitrate", - "container-format", "copyright", "encoder", - "encoder-version", "license", "nominal-bitrate", "title", - "video-codec"] + "application-name", "artist", "audio-codec", "bitrate", + "container-format", "copyright", "encoder", + "encoder-version", "license", "nominal-bitrate", "title", + "video-codec"] if key in tags_metadata]) if 'date' in tags_metadata: date = tags_metadata['date'] @@ -203,10 +108,346 @@ def store_metadata(media_entry, metadata): dt.get_year(), dt.get_month(), dt.get_day(), dt.get_hour(), dt.get_minute(), dt.get_second(), dt.get_microsecond()).isoformat() - + metadata['tags'] = tags # Only save this field if there's something to save if len(stored_metadata): media_entry.media_data_init( orig_metadata=stored_metadata) + + +class CommonVideoProcessor(MediaProcessor): + """ + Provides a base for various video processing steps + """ + acceptable_files = ['original', 'best_quality', 'webm_video'] + + def common_setup(self): + self.video_config = mgg \ + .global_config['plugins'][MEDIA_TYPE] + + # Pull down and set up the processing file + self.process_filename = get_process_filename( + self.entry, self.workbench, self.acceptable_files) + self.name_builder = FilenameBuilder(self.process_filename) + + self.transcoder = transcoders.VideoTranscoder() + self.did_transcode = False + + def copy_original(self): + # If we didn't transcode, then we need to keep the original + if not self.did_transcode or \ + (self.video_config['keep_original'] and self.did_transcode): + copy_original( + self.entry, self.process_filename, + self.name_builder.fill('{basename}{ext}')) + + def _keep_best(self): + """ + If there is no original, keep the best file that we have + """ + if not self.entry.media_files.get('best_quality'): + # Save the best quality file if no original? + if not self.entry.media_files.get('original') and \ + self.entry.media_files.get('webm_video'): + self.entry.media_files['best_quality'] = self.entry \ + .media_files['webm_video'] + + def _skip_processing(self, keyname, **kwargs): + file_metadata = self.entry.get_file_metadata(keyname) + + if not file_metadata: + return False + skip = True + + if keyname == 'webm_video': + if kwargs.get('medium_size') != file_metadata.get('medium_size'): + skip = False + elif kwargs.get('vp8_quality') != file_metadata.get('vp8_quality'): + skip = False + elif kwargs.get('vp8_threads') != file_metadata.get('vp8_threads'): + skip = False + elif kwargs.get('vorbis_quality') != \ + file_metadata.get('vorbis_quality'): + skip = False + elif keyname == 'thumb': + if kwargs.get('thumb_size') != file_metadata.get('thumb_size'): + skip = False + + return skip + + + def transcode(self, medium_size=None, vp8_quality=None, vp8_threads=None, + vorbis_quality=None): + progress_callback = ProgressCallback(self.entry) + tmp_dst = os.path.join(self.workbench.dir, + self.name_builder.fill('{basename}.medium.webm')) + + if not medium_size: + medium_size = ( + mgg.global_config['media:medium']['max_width'], + mgg.global_config['media:medium']['max_height']) + if not vp8_quality: + vp8_quality = self.video_config['vp8_quality'] + if not vp8_threads: + vp8_threads = self.video_config['vp8_threads'] + if not vorbis_quality: + vorbis_quality = self.video_config['vorbis_quality'] + + file_metadata = {'medium_size': medium_size, + 'vp8_threads': vp8_threads, + 'vp8_quality': vp8_quality, + 'vorbis_quality': vorbis_quality} + + if self._skip_processing('webm_video', **file_metadata): + return + + # Extract metadata and keep a record of it + metadata = self.transcoder.discover(self.process_filename) + store_metadata(self.entry, metadata) + + # Figure out whether or not we need to transcode this video or + # if we can skip it + if skip_transcode(metadata, medium_size): + _log.debug('Skipping transcoding') + + dst_dimensions = metadata['videowidth'], metadata['videoheight'] + + # If there is an original and transcoded, delete the transcoded + # since it must be of lower quality then the original + if self.entry.media_files.get('original') and \ + self.entry.media_files.get('webm_video'): + self.entry.media_files['webm_video'].delete() + + else: + self.transcoder.transcode(self.process_filename, tmp_dst, + vp8_quality=vp8_quality, + vp8_threads=vp8_threads, + vorbis_quality=vorbis_quality, + progress_callback=progress_callback, + dimensions=tuple(medium_size)) + + dst_dimensions = self.transcoder.dst_data.videowidth,\ + self.transcoder.dst_data.videoheight + + self._keep_best() + + # Push transcoded video to public storage + _log.debug('Saving medium...') + store_public(self.entry, 'webm_video', tmp_dst, + self.name_builder.fill('{basename}.medium.webm')) + _log.debug('Saved medium') + + self.entry.set_file_metadata('webm_video', **file_metadata) + + self.did_transcode = True + + # Save the width and height of the transcoded video + self.entry.media_data_init( + width=dst_dimensions[0], + height=dst_dimensions[1]) + + def generate_thumb(self, thumb_size=None): + # Temporary file for the video thumbnail (cleaned up with workbench) + tmp_thumb = os.path.join(self.workbench.dir, + self.name_builder.fill( + '{basename}.thumbnail.jpg')) + + if not thumb_size: + thumb_size = (mgg.global_config['media:thumb']['max_width'],) + + if self._skip_processing('thumb', thumb_size=thumb_size): + return + + # We will only use the width so that the correct scale is kept + transcoders.VideoThumbnailerMarkII( + self.process_filename, + tmp_thumb, + thumb_size[0]) + + # Checking if the thumbnail was correctly created. If it was not, + # then just give up. + if not os.path.exists (tmp_thumb): + return + + # Push the thumbnail to public storage + _log.debug('Saving thumbnail...') + store_public(self.entry, 'thumb', tmp_thumb, + self.name_builder.fill('{basename}.thumbnail.jpg')) + + self.entry.set_file_metadata('thumb', thumb_size=thumb_size) + +class InitialProcessor(CommonVideoProcessor): + """ + Initial processing steps for new video + """ + name = "initial" + description = "Initial processing" + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + if not state: + state = entry.state + return state in ( + "unprocessed", "failed") + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--medium_size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + parser.add_argument( + '--vp8_quality', + type=int, + help='Range 0..10') + + parser.add_argument( + '--vp8_threads', + type=int, + help='0 means number_of_CPUs - 1') + + parser.add_argument( + '--vorbis_quality', + type=float, + help='Range -0.1..1') + + parser.add_argument( + '--thumb_size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['medium_size', 'vp8_quality', 'vp8_threads', + 'vorbis_quality', 'thumb_size']) + + def process(self, medium_size=None, vp8_threads=None, vp8_quality=None, + vorbis_quality=None, thumb_size=None): + self.common_setup() + + self.transcode(medium_size=medium_size, vp8_quality=vp8_quality, + vp8_threads=vp8_threads, vorbis_quality=vorbis_quality) + + self.copy_original() + self.generate_thumb(thumb_size=thumb_size) + self.delete_queue_file() + + +class Resizer(CommonVideoProcessor): + """ + Video thumbnail resizing process steps for processed media + """ + name = 'resize' + description = 'Resize thumbnail' + thumb_size = 'thumb_size' + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + if not state: + state = entry.state + return state in 'processed' + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--thumb_size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + # Needed for gmg reprocess thumbs to work + parser.add_argument( + 'file', + nargs='?', + default='thumb', + choices=['thumb']) + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['thumb_size', 'file']) + + def process(self, thumb_size=None, file=None): + self.common_setup() + self.generate_thumb(thumb_size=thumb_size) + + +class Transcoder(CommonVideoProcessor): + """ + Transcoding processing steps for processed video + """ + name = 'transcode' + description = 'Re-transcode video' + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + if not state: + state = entry.state + return state in 'processed' + + @classmethod + def generate_parser(cls): + parser = argparse.ArgumentParser( + description=cls.description, + prog=cls.name) + + parser.add_argument( + '--medium_size', + nargs=2, + metavar=('max_width', 'max_height'), + type=int) + + parser.add_argument( + '--vp8_quality', + type=int, + help='Range 0..10') + + parser.add_argument( + '--vp8_threads', + type=int, + help='0 means number_of_CPUs - 1') + + parser.add_argument( + '--vorbis_quality', + type=float, + help='Range -0.1..1') + + return parser + + @classmethod + def args_to_request(cls, args): + return request_from_args( + args, ['medium_size', 'vp8_threads', 'vp8_quality', + 'vorbis_quality']) + + def process(self, medium_size=None, vp8_quality=None, vp8_threads=None, + vorbis_quality=None): + self.common_setup() + self.transcode(medium_size=medium_size, vp8_threads=vp8_threads, + vp8_quality=vp8_quality, vorbis_quality=vorbis_quality) + + +class VideoProcessingManager(ProcessingManager): + def __init__(self): + super(self.__class__, self).__init__() + self.add_processor(InitialProcessor) + self.add_processor(Resizer) + self.add_processor(Transcoder) diff --git a/mediagoblin/media_types/video/transcoders.py b/mediagoblin/media_types/video/transcoders.py index 90a767dd..9d6b7655 100644 --- a/mediagoblin/media_types/video/transcoders.py +++ b/mediagoblin/media_types/video/transcoders.py @@ -22,9 +22,15 @@ import logging import urllib import multiprocessing import gobject + +old_argv = sys.argv +sys.argv = [] + import pygst pygst.require('0.10') import gst + +sys.argv = old_argv import struct try: from PIL import Image diff --git a/mediagoblin/media_types/video/util.py b/mediagoblin/media_types/video/util.py index 5765ecfb..beb10129 100644 --- a/mediagoblin/media_types/video/util.py +++ b/mediagoblin/media_types/video/util.py @@ -21,13 +21,13 @@ from mediagoblin import mg_globals as mgg _log = logging.getLogger(__name__) -def skip_transcode(metadata): +def skip_transcode(metadata, size): ''' Checks video metadata against configuration values for skip_transcode. Returns True if the video matches the requirements in the configuration. ''' - config = mgg.global_config['media_type:mediagoblin.media_types.video']\ + config = mgg.global_config['plugins']['mediagoblin.media_types.video']\ ['skip_transcode'] medium_config = mgg.global_config['media:medium'] @@ -51,9 +51,9 @@ def skip_transcode(metadata): return False if config['dimensions_match']: - if not metadata['videoheight'] <= medium_config['max_height']: + if not metadata['videoheight'] <= size[1]: return False - if not metadata['videowidth'] <= medium_config['max_width']: + if not metadata['videowidth'] <= size[0]: return False return True diff --git a/mediagoblin/messages.py b/mediagoblin/messages.py index 80d8ece7..d58f13d4 100644 --- a/mediagoblin/messages.py +++ b/mediagoblin/messages.py @@ -14,16 +14,24 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +from mediagoblin.tools import common + DEBUG = 'debug' INFO = 'info' SUCCESS = 'success' WARNING = 'warning' ERROR = 'error' +ADD_MESSAGE_TEST = [] + def add_message(request, level, text): messages = request.session.setdefault('messages', []) messages.append({'level': level, 'text': text}) + + if common.TESTS_ENABLED: + ADD_MESSAGE_TEST.append(messages) + request.session.save() @@ -33,4 +41,10 @@ def fetch_messages(request, clear_from_session=True): # Save that we removed the messages from the session request.session['messages'] = [] request.session.save() + return messages + + +def clear_add_message(): + global ADD_MESSAGE_TEST + ADD_MESSAGE_TEST = [] diff --git a/mediagoblin/admin/__init__.py b/mediagoblin/moderation/__init__.py index 719b56e7..719b56e7 100644 --- a/mediagoblin/admin/__init__.py +++ b/mediagoblin/moderation/__init__.py diff --git a/mediagoblin/moderation/forms.py b/mediagoblin/moderation/forms.py new file mode 100644 index 00000000..72305b29 --- /dev/null +++ b/mediagoblin/moderation/forms.py @@ -0,0 +1,149 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import wtforms +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ + +ACTION_CHOICES = [ + (u'takeaway', _(u'Take away privilege')), + (u'userban', _(u'Ban the user')), + (u'sendmessage', _(u'Send the user a message')), + (u'delete', _(u'Delete the content'))] + +class MultiCheckboxField(wtforms.SelectMultipleField): + """ + A multiple-select, except displays a list of checkboxes. + + Iterating the field will produce subfields, allowing custom rendering of + the enclosed checkbox fields. + + code from http://wtforms.simplecodes.com/docs/1.0.4/specific_problems.html + """ + widget = wtforms.widgets.ListWidget(prefix_label=False) + option_widget = wtforms.widgets.CheckboxInput() + + +# ============ Forms for mediagoblin.moderation.user page ================== # + +class PrivilegeAddRemoveForm(wtforms.Form): + """ + This form is used by an admin to give/take away a privilege directly from + their user page. + """ + privilege_name = wtforms.HiddenField('',[wtforms.validators.required()]) + +class BanForm(wtforms.Form): + """ + This form is used by an admin to ban a user directly from their user page. + """ + user_banned_until = wtforms.DateField( + _(u'User will be banned until:'), + format='%Y-%m-%d', + validators=[wtforms.validators.optional()]) + why_user_was_banned = wtforms.TextAreaField( + _(u'Why are you banning this User?'), + validators=[wtforms.validators.optional()]) + +# =========== Forms for mediagoblin.moderation.report page ================= # + +class ReportResolutionForm(wtforms.Form): + """ + This form carries all the information necessary to take punitive actions + against a user who created content that has been reported. + + :param action_to_resolve A list of Unicode objects representing + a choice from the ACTION_CHOICES const- + -ant. Every choice passed affects what + punitive actions will be taken against + the user. + + :param targeted_user A HiddenField object that holds the id + of the user that was reported. + + :param take_away_privileges A list of Unicode objects which repres- + -ent the privileges that are being tak- + -en away. This field is optional and + only relevant if u'takeaway' is in the + `action_to_resolve` list. + + :param user_banned_until A DateField object that holds the date + that the user will be unbanned. This + field is optional and only relevant if + u'userban' is in the action_to_resolve + list. If the user is being banned and + this field is blank, the user is banned + indefinitely. + + :param why_user_was_banned A TextArea object that holds the + reason that a user was banned, to disp- + -lay to them when they try to log in. + This field is optional and only relevant + if u'userban' is in the + `action_to_resolve` list. + + :param message_to_user A TextArea object that holds a message + which will be emailed to the user. This + is only relevant if the u'sendmessage' + option is in the `action_to_resolve` + list. + + :param resolution_content A TextArea object that is required for + every report filed. It represents the + reasons that the moderator/admin resol- + -ved the report in such a way. + """ + action_to_resolve = MultiCheckboxField( + _(u'What action will you take to resolve the report?'), + validators=[wtforms.validators.optional()], + choices=ACTION_CHOICES) + targeted_user = wtforms.HiddenField('', + validators=[wtforms.validators.required()]) + take_away_privileges = wtforms.SelectMultipleField( + _(u'What privileges will you take away?'), + validators=[wtforms.validators.optional()]) + user_banned_until = wtforms.DateField( + _(u'User will be banned until:'), + format='%Y-%m-%d', + validators=[wtforms.validators.optional()]) + why_user_was_banned = wtforms.TextAreaField( + validators=[wtforms.validators.optional()]) + message_to_user = wtforms.TextAreaField( + validators=[wtforms.validators.optional()]) + resolution_content = wtforms.TextAreaField() + +# ======== Forms for mediagoblin.moderation.report_panel page ============== # + +class ReportPanelSortingForm(wtforms.Form): + """ + This form is used for sorting and filtering through different reports in + the mediagoblin.moderation.reports_panel view. + + """ + active_p = wtforms.IntegerField( + validators=[wtforms.validators.optional()]) + closed_p = wtforms.IntegerField( + validators=[wtforms.validators.optional()]) + reported_user = wtforms.IntegerField( + validators=[wtforms.validators.optional()]) + reporter = wtforms.IntegerField( + validators=[wtforms.validators.optional()]) + +class UserPanelSortingForm(wtforms.Form): + """ + This form is used for sorting different reports. + """ + p = wtforms.IntegerField( + validators=[wtforms.validators.optional()]) diff --git a/mediagoblin/moderation/routing.py b/mediagoblin/moderation/routing.py new file mode 100644 index 00000000..ba10bc6d --- /dev/null +++ b/mediagoblin/moderation/routing.py @@ -0,0 +1,38 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. + +moderation_routes = [ + ('mediagoblin.moderation.media_panel', + '/media/', + 'mediagoblin.moderation.views:moderation_media_processing_panel'), + ('mediagoblin.moderation.users', + '/users/', + 'mediagoblin.moderation.views:moderation_users_panel'), + ('mediagoblin.moderation.reports', + '/reports/', + 'mediagoblin.moderation.views:moderation_reports_panel'), + ('mediagoblin.moderation.users_detail', + '/users/<string:user>/', + 'mediagoblin.moderation.views:moderation_users_detail'), + ('mediagoblin.moderation.give_or_take_away_privilege', + '/users/<string:user>/privilege/', + 'mediagoblin.moderation.views:give_or_take_away_privilege'), + ('mediagoblin.moderation.ban_or_unban', + '/users/<string:user>/ban/', + 'mediagoblin.moderation.views:ban_or_unban'), + ('mediagoblin.moderation.reports_detail', + '/reports/<int:report_id>/', + 'mediagoblin.moderation.views:moderation_reports_detail')] diff --git a/mediagoblin/moderation/tools.py b/mediagoblin/moderation/tools.py new file mode 100644 index 00000000..e0337536 --- /dev/null +++ b/mediagoblin/moderation/tools.py @@ -0,0 +1,217 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin import mg_globals +from mediagoblin.db.models import User, Privilege, UserBan +from mediagoblin.db.base import Session +from mediagoblin.tools.mail import send_email +from mediagoblin.tools.response import redirect +from datetime import datetime +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ + +def take_punitive_actions(request, form, report, user): + message_body ='' + + # The bulk of this action is running through all of the different + # punitive actions that a moderator could take. + if u'takeaway' in form.action_to_resolve.data: + for privilege_name in form.take_away_privileges.data: + take_away_privileges(user.username, privilege_name) + form.resolution_content.data += \ + u"\n{mod} took away {user}\'s {privilege} privileges.".format( + mod=request.user.username, + user=user.username, + privilege=privilege_name) + + # If the moderator elects to ban the user, a new instance of user_ban + # will be created. + if u'userban' in form.action_to_resolve.data: + user_ban = ban_user(form.targeted_user.data, + expiration_date=form.user_banned_until.data, + reason=form.why_user_was_banned.data) + Session.add(user_ban) + form.resolution_content.data += \ + u"\n{mod} banned user {user} {expiration_date}.".format( + mod=request.user.username, + user=user.username, + expiration_date = ( + "until {date}".format(date=form.user_banned_until.data) + if form.user_banned_until.data + else "indefinitely" + ) + ) + + # If the moderator elects to send a warning message. An email will be + # sent to the email address given at sign up + if u'sendmessage' in form.action_to_resolve.data: + message_body = form.message_to_user.data + form.resolution_content.data += \ + u"\n{mod} sent a warning email to the {user}.".format( + mod=request.user.username, + user=user.username) + + if u'delete' in form.action_to_resolve.data and \ + report.is_comment_report(): + deleted_comment = report.comment + Session.delete(deleted_comment) + form.resolution_content.data += \ + u"\n{mod} deleted the comment.".format( + mod=request.user.username) + elif u'delete' in form.action_to_resolve.data and \ + report.is_media_entry_report(): + deleted_media = report.media_entry + deleted_media.delete() + form.resolution_content.data += \ + u"\n{mod} deleted the media entry.".format( + mod=request.user.username) + report.archive( + resolver_id=request.user.id, + resolved=datetime.now(), + result=form.resolution_content.data) + + Session.add(report) + Session.commit() + if message_body: + send_email( + mg_globals.app_config['email_sender_address'], + [user.email], + _('Warning from')+ '- {moderator} '.format( + moderator=request.user.username), + message_body) + + return redirect( + request, + 'mediagoblin.moderation.users_detail', + user=user.username) + + +def take_away_privileges(user,*privileges): + """ + Take away all of the privileges passed as arguments. + + :param user A Unicode object representing the target user's + User.username value. + + :param privileges A variable number of Unicode objects describing + the privileges being taken away. + + + :returns True If ALL of the privileges were taken away + successfully. + + :returns False If ANY of the privileges were not taken away + successfully. This means the user did not have + (one of) the privilege(s) to begin with. + """ + if len(privileges) == 1: + privilege = Privilege.query.filter( + Privilege.privilege_name==privileges[0]).first() + user = User.query.filter( + User.username==user).first() + if privilege in user.all_privileges: + user.all_privileges.remove(privilege) + return True + return False + + elif len(privileges) > 1: + return (take_away_privileges(user, privileges[0]) and \ + take_away_privileges(user, *privileges[1:])) + +def give_privileges(user,*privileges): + """ + Take away all of the privileges passed as arguments. + + :param user A Unicode object representing the target user's + User.username value. + + :param privileges A variable number of Unicode objects describing + the privileges being granted. + + + :returns True If ALL of the privileges were granted successf- + -ully. + + :returns False If ANY of the privileges were not granted succ- + essfully. This means the user already had (one + of) the privilege(s) to begin with. + """ + if len(privileges) == 1: + privilege = Privilege.query.filter( + Privilege.privilege_name==privileges[0]).first() + user = User.query.filter( + User.username==user).first() + if privilege not in user.all_privileges: + user.all_privileges.append(privilege) + return True + return False + + elif len(privileges) > 1: + return (give_privileges(user, privileges[0]) and \ + give_privileges(user, *privileges[1:])) + +def ban_user(user_id, expiration_date=None, reason=None): + """ + This function is used to ban a user. If the user is already banned, the + function returns False. If the user is not already banned, this function + bans the user using the arguments to build a new UserBan object. + + :returns False if the user is already banned and the ban is not updated + :returns UserBan object if there is a new ban that was created. + """ + user_ban =UserBan.query.filter( + UserBan.user_id==user_id) + if user_ban.count(): + return False + new_user_ban = UserBan( + user_id=user_id, + expiration_date=expiration_date, + reason=reason) + return new_user_ban + +def unban_user(user_id): + """ + This function is used to unban a user. If the user is not currently banned, + nothing happens. + + :returns True if the operation was completed successfully and the user + has been unbanned + :returns False if the user was never banned. + """ + user_ban = UserBan.query.filter( + UserBan.user_id==user_id) + if user_ban.count() == 0: + return False + user_ban.first().delete() + return True + +def parse_report_panel_settings(form): + """ + This function parses the url arguments to which are used to filter reports + in the reports panel view. More filters can be added to make a usuable + search function. + + :returns A dictionary of sqlalchemy-usable filters. + """ + filters = {} + + if form.validate(): + filters['reported_user_id'] = form.reported_user.data + filters['reporter_id'] = form.reporter.data + + filters = dict((k, v) + for k, v in filters.iteritems() if v) + + return filters diff --git a/mediagoblin/moderation/views.py b/mediagoblin/moderation/views.py new file mode 100644 index 00000000..f4de11ad --- /dev/null +++ b/mediagoblin/moderation/views.py @@ -0,0 +1,219 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +from mediagoblin.db.models import (MediaEntry, User,ReportBase, Privilege, + UserBan) +from mediagoblin.decorators import (require_admin_or_moderator_login, + active_user_from_url, user_has_privilege, + allow_reporting) +from mediagoblin.tools.response import render_to_response, redirect +from mediagoblin.moderation import forms as moderation_forms +from mediagoblin.moderation.tools import (take_punitive_actions, \ + take_away_privileges, give_privileges, ban_user, unban_user, \ + parse_report_panel_settings) +from math import ceil + +@require_admin_or_moderator_login +def moderation_media_processing_panel(request): + ''' + Show the global media processing panel for this instance + ''' + processing_entries = MediaEntry.query.filter_by(state = u'processing').\ + order_by(MediaEntry.created.desc()) + + # Get media entries which have failed to process + failed_entries = MediaEntry.query.filter_by(state = u'failed').\ + order_by(MediaEntry.created.desc()) + + processed_entries = MediaEntry.query.filter_by(state = u'processed').\ + order_by(MediaEntry.created.desc()).limit(10) + + # Render to response + return render_to_response( + request, + 'mediagoblin/moderation/media_panel.html', + {'processing_entries': processing_entries, + 'failed_entries': failed_entries, + 'processed_entries': processed_entries}) + +@require_admin_or_moderator_login +def moderation_users_panel(request): + ''' + Show the global panel for monitoring users in this instance + ''' + current_page = 1 + if len(request.args) > 0: + form = moderation_forms.UserPanelSortingForm(request.args) + if form.validate(): + current_page = form.p.data or 1 + + all_user_list = User.query + user_list = all_user_list.order_by( + User.created.desc()).offset( + (current_page-1)*10).limit(10) + last_page = int(ceil(all_user_list.count()/10.)) + + return render_to_response( + request, + 'mediagoblin/moderation/user_panel.html', + {'user_list': user_list, + 'current_page':current_page, + 'last_page':last_page}) + +@require_admin_or_moderator_login +def moderation_users_detail(request): + ''' + Shows details about a particular user. + ''' + user = User.query.filter_by(username=request.matchdict['user']).first() + active_reports = user.reports_filed_on.filter( + ReportBase.resolved==None).limit(5) + closed_reports = user.reports_filed_on.filter( + ReportBase.resolved!=None).all() + privileges = Privilege.query + user_banned = UserBan.query.get(user.id) + ban_form = moderation_forms.BanForm() + + return render_to_response( + request, + 'mediagoblin/moderation/user.html', + {'user':user, + 'privileges': privileges, + 'reports':active_reports, + 'user_banned':user_banned, + 'ban_form':ban_form}) + +@require_admin_or_moderator_login +@allow_reporting +def moderation_reports_panel(request): + ''' + Show the global panel for monitoring reports filed against comments or + media entries for this instance. + ''' + filters = [] + active_settings, closed_settings = {'current_page':1}, {'current_page':1} + + if len(request.args) > 0: + form = moderation_forms.ReportPanelSortingForm(request.args) + if form.validate(): + filters = parse_report_panel_settings(form) + active_settings['current_page'] = form.active_p.data or 1 + closed_settings['current_page'] = form.closed_p.data or 1 + filters = [ + getattr(ReportBase,key)==val + for key,val in filters.viewitems()] + + all_active = ReportBase.query.filter( + ReportBase.resolved==None).filter( + *filters) + all_closed = ReportBase.query.filter( + ReportBase.resolved!=None).filter( + *filters) + + # report_list and closed_report_list are the two lists of up to 10 + # items which are actually passed to the user in this request + report_list = all_active.order_by( + ReportBase.created.desc()).offset( + (active_settings['current_page']-1)*10).limit(10) + closed_report_list = all_closed.order_by( + ReportBase.created.desc()).offset( + (closed_settings['current_page']-1)*10).limit(10) + + active_settings['last_page'] = int(ceil(all_active.count()/10.)) + closed_settings['last_page'] = int(ceil(all_closed.count()/10.)) + # Render to response + return render_to_response( + request, + 'mediagoblin/moderation/report_panel.html', + {'report_list':report_list, + 'closed_report_list':closed_report_list, + 'active_settings':active_settings, + 'closed_settings':closed_settings}) + +@require_admin_or_moderator_login +@allow_reporting +def moderation_reports_detail(request): + """ + This is the page an admin or moderator goes to see the details of a report. + The report can be resolved or unresolved. This is also the page that a mod- + erator would go to to take an action to resolve a report. + """ + form = moderation_forms.ReportResolutionForm(request.form) + report = ReportBase.query.get(request.matchdict['report_id']) + + form.take_away_privileges.choices = [ + (s.privilege_name,s.privilege_name.title()) \ + for s in report.reported_user.all_privileges + ] + + if request.method == "POST" and form.validate() and not ( + not request.user.has_privilege(u'admin') and + report.reported_user.has_privilege(u'admin')): + + user = User.query.get(form.targeted_user.data) + return take_punitive_actions(request, form, report, user) + + + form.targeted_user.data = report.reported_user_id + + return render_to_response( + request, + 'mediagoblin/moderation/report.html', + {'report':report, + 'form':form}) + +@user_has_privilege(u'admin') +@active_user_from_url +def give_or_take_away_privilege(request, url_user): + ''' + A form action to give or take away a particular privilege from a user. + Can only be used by an admin. + ''' + form = moderation_forms.PrivilegeAddRemoveForm(request.form) + if request.method == "POST" and form.validate(): + privilege = Privilege.query.filter( + Privilege.privilege_name==form.privilege_name.data).one() + if not take_away_privileges( + url_user.username, form.privilege_name.data): + + give_privileges(url_user.username, form.privilege_name.data) + url_user.save() + + return redirect( + request, + 'mediagoblin.moderation.users_detail', + user=url_user.username) + +@user_has_privilege(u'admin') +@active_user_from_url +def ban_or_unban(request, url_user): + """ + A page to ban or unban a user. Only can be used by an admin. + """ + form = moderation_forms.BanForm(request.form) + if request.method == "POST" and form.validate(): + already_banned = unban_user(url_user.id) + same_as_requesting_user = (request.user.id == url_user.id) + if not already_banned and not same_as_requesting_user: + user_ban = ban_user(url_user.id, + expiration_date = form.user_banned_until.data, + reason = form.why_user_was_banned.data) + user_ban.save() + return redirect( + request, + 'mediagoblin.moderation.users_detail', + user=url_user.username) diff --git a/mediagoblin/notifications/__init__.py b/mediagoblin/notifications/__init__.py new file mode 100644 index 00000000..b6f9f478 --- /dev/null +++ b/mediagoblin/notifications/__init__.py @@ -0,0 +1,155 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import logging + +from mediagoblin.db.models import Notification, \ + CommentNotification, CommentSubscription, User +from mediagoblin.notifications.task import email_notification_task +from mediagoblin.notifications.tools import generate_comment_message + +_log = logging.getLogger(__name__) + +def trigger_notification(comment, media_entry, request): + ''' + Send out notifications about a new comment. + ''' + subscriptions = CommentSubscription.query.filter_by( + media_entry_id=media_entry.id).all() + + for subscription in subscriptions: + if not subscription.notify: + continue + + if comment.get_author == subscription.user: + continue + + cn = CommentNotification( + user_id=subscription.user_id, + subject_id=comment.id) + + cn.save() + + if subscription.send_email: + message = generate_comment_message( + subscription.user, + comment, + media_entry, + request) + + from mediagoblin.notifications.task import email_notification_task + email_notification_task.apply_async([cn.id, message]) + + +def mark_notification_seen(notification): + if notification: + notification.seen = True + notification.save() + + +def mark_comment_notification_seen(comment_id, user): + notification = CommentNotification.query.filter_by( + user_id=user.id, + subject_id=comment_id).first() + + _log.debug('Marking {0} as seen.'.format(notification)) + + mark_notification_seen(notification) + + +def get_comment_subscription(user_id, media_entry_id): + return CommentSubscription.query.filter_by( + user_id=user_id, + media_entry_id=media_entry_id).first() + +def add_comment_subscription(user, media_entry): + ''' + Create a comment subscription for a User on a MediaEntry. + + Uses the User's wants_comment_notification to set email notifications for + the subscription to enabled/disabled. + ''' + cn = get_comment_subscription(user.id, media_entry.id) + + if not cn: + cn = CommentSubscription( + user_id=user.id, + media_entry_id=media_entry.id) + + cn.notify = True + + if not user.wants_comment_notification: + cn.send_email = False + + cn.save() + + +def silence_comment_subscription(user, media_entry): + ''' + Silence a subscription so that the user is never notified in any way about + new comments on an entry + ''' + cn = get_comment_subscription(user.id, media_entry.id) + + if cn: + cn.notify = False + cn.send_email = False + cn.save() + + +def remove_comment_subscription(user, media_entry): + cn = get_comment_subscription(user.id, media_entry.id) + + if cn: + cn.delete() + + +NOTIFICATION_FETCH_LIMIT = 100 + + +def get_notifications(user_id, only_unseen=True): + query = Notification.query.filter_by(user_id=user_id) + wants_notifications = User.query.filter_by(id=user_id).first()\ + .wants_notifications + + # If the user does not want notifications, don't return any + if not wants_notifications: + return None + + if only_unseen: + query = query.filter_by(seen=False) + + notifications = query.limit( + NOTIFICATION_FETCH_LIMIT).all() + + return notifications + + +def get_notification_count(user_id, only_unseen=True): + query = Notification.query.filter_by(user_id=user_id) + wants_notifications = User.query.filter_by(id=user_id).first()\ + .wants_notifications + + if only_unseen: + query = query.filter_by(seen=False) + + # If the user doesn't want notifications, don't show any + if not wants_notifications: + count = None + else: + count = query.count() + + return count diff --git a/mediagoblin/notifications/routing.py b/mediagoblin/notifications/routing.py new file mode 100644 index 00000000..cd7bbc21 --- /dev/null +++ b/mediagoblin/notifications/routing.py @@ -0,0 +1,29 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.tools.routing import add_route + +add_route('mediagoblin.notifications.subscribe_comments', + '/u/<string:user>/m/<string:media>/notifications/subscribe/comments/', + 'mediagoblin.notifications.views:subscribe_comments') + +add_route('mediagoblin.notifications.silence_comments', + '/u/<string:user>/m/<string:media>/notifications/silence/', + 'mediagoblin.notifications.views:silence_comments') + +add_route('mediagoblin.notifications.mark_all_comment_notifications_seen', + '/notifications/comments/mark_all_seen/', + 'mediagoblin.notifications.views:mark_all_comment_notifications_seen') diff --git a/mediagoblin/notifications/task.py b/mediagoblin/notifications/task.py new file mode 100644 index 00000000..52573b57 --- /dev/null +++ b/mediagoblin/notifications/task.py @@ -0,0 +1,46 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import logging + +from celery import registry +from celery.task import Task + +from mediagoblin.tools.mail import send_email +from mediagoblin.db.models import CommentNotification + + +_log = logging.getLogger(__name__) + + +class EmailNotificationTask(Task): + ''' + Celery notification task. + + This task is executed by celeryd to offload long-running operations from + the web server. + ''' + def run(self, notification_id, message): + cn = CommentNotification.query.filter_by(id=notification_id).first() + _log.info('Sending notification email about {0}'.format(cn)) + + return send_email( + message['from'], + [message['to']], + message['subject'], + message['body']) + +email_notification_task = registry.tasks[EmailNotificationTask.name] diff --git a/mediagoblin/notifications/tools.py b/mediagoblin/notifications/tools.py new file mode 100644 index 00000000..25432780 --- /dev/null +++ b/mediagoblin/notifications/tools.py @@ -0,0 +1,55 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.tools.template import render_template +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin import mg_globals + +def generate_comment_message(user, comment, media, request): + """ + Sends comment email to user when a comment is made on their media. + + Args: + - user: the user object to whom the email is sent + - comment: the comment object referencing user's media + - media: the media object the comment is about + - request: the request + """ + + comment_url = request.urlgen( + 'mediagoblin.user_pages.media_home.view_comment', + comment=comment.id, + user=media.get_uploader.username, + media=media.slug_or_id, + qualified=True) + '#comment' + + comment_author = comment.get_author.username + + rendered_email = render_template( + request, 'mediagoblin/user_pages/comment_email.txt', + {'username': user.username, + 'comment_author': comment_author, + 'comment_content': comment.content, + 'comment_url': comment_url}) + + return { + 'from': mg_globals.app_config['email_sender_address'], + 'to': user.email, + 'subject': '{instance_title} - {comment_author} '.format( + comment_author=comment_author, + instance_title=mg_globals.app_config['html_title']) \ + + _('commented on your post'), + 'body': rendered_email} diff --git a/mediagoblin/notifications/views.py b/mediagoblin/notifications/views.py new file mode 100644 index 00000000..cfe66b2e --- /dev/null +++ b/mediagoblin/notifications/views.py @@ -0,0 +1,65 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.tools.response import redirect +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.decorators import get_user_media_entry, require_active_login +from mediagoblin import messages + +from mediagoblin.notifications import (add_comment_subscription, + silence_comment_subscription, mark_comment_notification_seen, + get_notifications) + + +@get_user_media_entry +@require_active_login +def subscribe_comments(request, media): + + add_comment_subscription(request.user, media) + + messages.add_message(request, + messages.SUCCESS, + _('Subscribed to comments on %s!') + % media.title) + + return redirect(request, location=media.url_for_self(request.urlgen)) + + +@get_user_media_entry +@require_active_login +def silence_comments(request, media): + silence_comment_subscription(request.user, media) + + messages.add_message(request, + messages.SUCCESS, + _('You will not receive notifications for comments on' + ' %s.') % media.title) + + return redirect(request, location=media.url_for_self(request.urlgen)) + + +@require_active_login +def mark_all_comment_notifications_seen(request): + """ + Marks all comment notifications seen. + """ + for comment in get_notifications(request.user.id): + mark_comment_notification_seen(comment.subject_id, request.user) + + if request.GET.get('next'): + return redirect(request, location=request.GET.get('next')) + else: + return redirect(request, 'index') diff --git a/mediagoblin/templates/mediagoblin/bits/body-start.html b/mediagoblin/oauth/__init__.py index bb7b9762..719b56e7 100644 --- a/mediagoblin/templates/mediagoblin/bits/body-start.html +++ b/mediagoblin/oauth/__init__.py @@ -1,4 +1,3 @@ -{# # GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # @@ -14,4 +13,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/>. --#} + diff --git a/mediagoblin/oauth/exceptions.py b/mediagoblin/oauth/exceptions.py new file mode 100644 index 00000000..5eccba34 --- /dev/null +++ b/mediagoblin/oauth/exceptions.py @@ -0,0 +1,18 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. + +class ValidationException(Exception): + pass diff --git a/mediagoblin/oauth/forms.py b/mediagoblin/oauth/forms.py new file mode 100644 index 00000000..94c7cb52 --- /dev/null +++ b/mediagoblin/oauth/forms.py @@ -0,0 +1,7 @@ +import wtforms + +class AuthorizeForm(wtforms.Form): + """ Form used to authorize the request token """ + + oauth_token = wtforms.HiddenField("oauth_token") + oauth_verifier = wtforms.HiddenField("oauth_verifier") diff --git a/mediagoblin/oauth/oauth.py b/mediagoblin/oauth/oauth.py new file mode 100644 index 00000000..8229c47d --- /dev/null +++ b/mediagoblin/oauth/oauth.py @@ -0,0 +1,132 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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 oauthlib.common import Request +from oauthlib.oauth1 import RequestValidator + +from mediagoblin.db.models import NonceTimestamp, Client, RequestToken, AccessToken + + + +class GMGRequestValidator(RequestValidator): + + enforce_ssl = False + + def __init__(self, data=None, *args, **kwargs): + self.POST = data + super(GMGRequestValidator, self).__init__(*args, **kwargs) + + def save_request_token(self, token, request): + """ Saves request token in db """ + client_id = self.POST[u"oauth_consumer_key"] + + request_token = RequestToken( + token=token["oauth_token"], + secret=token["oauth_token_secret"], + ) + request_token.client = client_id + if u"oauth_callback" in self.POST: + request_token.callback = self.POST[u"oauth_callback"] + request_token.save() + + def save_verifier(self, token, verifier, request): + """ Saves the oauth request verifier """ + request_token = RequestToken.query.filter_by(token=token).first() + request_token.verifier = verifier["oauth_verifier"] + request_token.save() + + def save_access_token(self, token, request): + """ Saves access token in db """ + access_token = AccessToken( + token=token["oauth_token"], + secret=token["oauth_token_secret"], + ) + access_token.request_token = request.oauth_token + request_token = RequestToken.query.filter_by(token=request.oauth_token).first() + access_token.user = request_token.user + access_token.save() + + def get_realms(*args, **kwargs): + """ Currently a stub - called when making AccessTokens """ + return list() + + def validate_timestamp_and_nonce(self, client_key, timestamp, + nonce, request, request_token=None, + access_token=None): + nc = NonceTimestamp.query.filter_by(timestamp=timestamp, nonce=nonce) + nc = nc.first() + if nc is None: + return True + + return False + + def validate_client_key(self, client_key, request): + """ Verifies client exists with id of client_key """ + client = Client.query.filter_by(id=client_key).first() + if client is None: + return False + + return True + + def validate_access_token(self, client_key, token, request): + """ Verifies token exists for client with id of client_key """ + client = Client.query.filter_by(id=client_key).first() + token = AccessToken.query.filter_by(token=token) + token = token.first() + + if token is None: + return False + + request_token = RequestToken.query.filter_by(token=token.request_token) + request_token = request_token.first() + + if client.id != request_token.client: + return False + + return True + + def validate_realms(self, *args, **kwargs): + """ Would validate reals however not using these yet. """ + return True # implement when realms are implemented + + + def get_client_secret(self, client_key, request): + """ Retrives a client secret with from a client with an id of client_key """ + client = Client.query.filter_by(id=client_key).first() + return client.secret + + def get_access_token_secret(self, client_key, token, request): + access_token = AccessToken.query.filter_by(token=token).first() + return access_token.secret + +class GMGRequest(Request): + """ + Fills in data to produce a oauth.common.Request object from a + werkzeug Request object + """ + + def __init__(self, request, *args, **kwargs): + """ + :param request: werkzeug request object + + any extra params are passed to oauthlib.common.Request object + """ + kwargs["uri"] = kwargs.get("uri", request.url) + kwargs["http_method"] = kwargs.get("http_method", request.method) + kwargs["body"] = kwargs.get("body", request.get_data()) + kwargs["headers"] = kwargs.get("headers", dict(request.headers)) + + super(GMGRequest, self).__init__(*args, **kwargs) diff --git a/mediagoblin/oauth/routing.py b/mediagoblin/oauth/routing.py new file mode 100644 index 00000000..e45077bb --- /dev/null +++ b/mediagoblin/oauth/routing.py @@ -0,0 +1,43 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.tools.routing import add_route + +# client registration & oauth +add_route( + "mediagoblin.oauth", + "/api/client/register", + "mediagoblin.oauth.views:client_register" + ) + +add_route( + "mediagoblin.oauth", + "/oauth/request_token", + "mediagoblin.oauth.views:request_token" + ) + +add_route( + "mediagoblin.oauth", + "/oauth/authorize", + "mediagoblin.oauth.views:authorize", + ) + +add_route( + "mediagoblin.oauth", + "/oauth/access_token", + "mediagoblin.oauth.views:access_token" + ) + diff --git a/mediagoblin/oauth/tools/__init__.py b/mediagoblin/oauth/tools/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/mediagoblin/oauth/tools/__init__.py diff --git a/mediagoblin/admin/routing.py b/mediagoblin/oauth/tools/forms.py index 29515f12..e3eb3298 100644 --- a/mediagoblin/admin/routing.py +++ b/mediagoblin/oauth/tools/forms.py @@ -14,7 +14,12 @@ # 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/>. -admin_routes = [ - ('mediagoblin.admin.panel', - '/panel', - 'mediagoblin.admin.views:admin_processing_panel')] +class WTFormData(dict): + """ + Provides a WTForm usable dictionary + """ + def getlist(self, key): + v = self[key] + if not isinstance(v, (list, tuple)): + v = [v] + return v diff --git a/mediagoblin/oauth/tools/request.py b/mediagoblin/oauth/tools/request.py new file mode 100644 index 00000000..5ce2da77 --- /dev/null +++ b/mediagoblin/oauth/tools/request.py @@ -0,0 +1,35 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. + +def decode_authorization_header(header): + """ Decodes a HTTP Authorization Header to python dictionary """ + authorization = header.get("Authorization", "").lstrip(" ").lstrip("OAuth") + tokens = {} + + for param in authorization.split(","): + try: + key, value = param.split("=") + except ValueError: + continue + + key = key.lstrip(" ") + value = value.lstrip(" ").lstrip('"') + value = value.rstrip(" ").rstrip('"') + + tokens[key] = value + + return tokens + diff --git a/mediagoblin/oauth/views.py b/mediagoblin/oauth/views.py new file mode 100644 index 00000000..14c8ab14 --- /dev/null +++ b/mediagoblin/oauth/views.py @@ -0,0 +1,339 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import datetime + +from oauthlib.oauth1 import (RequestTokenEndpoint, AuthorizationEndpoint, + AccessTokenEndpoint) + +from mediagoblin.decorators import require_active_login +from mediagoblin.tools.translate import pass_to_ugettext +from mediagoblin.meddleware.csrf import csrf_exempt +from mediagoblin.tools.request import decode_request +from mediagoblin.tools.response import (render_to_response, redirect, + json_response, render_400, + form_response) +from mediagoblin.tools.crypto import random_string +from mediagoblin.tools.validator import validate_email, validate_url +from mediagoblin.oauth.forms import AuthorizeForm +from mediagoblin.oauth.oauth import GMGRequestValidator, GMGRequest +from mediagoblin.oauth.tools.request import decode_authorization_header +from mediagoblin.oauth.tools.forms import WTFormData +from mediagoblin.db.models import NonceTimestamp, Client, RequestToken + +# possible client types +client_types = ["web", "native"] # currently what pump supports + +@csrf_exempt +def client_register(request): + """ Endpoint for client registration """ + try: + data = decode_request(request) + except ValueError: + error = "Could not decode data." + return json_response({"error": error}, status=400) + + if data is "": + error = "Unknown Content-Type" + return json_response({"error": error}, status=400) + + if "type" not in data: + error = "No registration type provided." + return json_response({"error": error}, status=400) + if data.get("application_type", None) not in client_types: + error = "Unknown application_type." + return json_response({"error": error}, status=400) + + client_type = data["type"] + + if client_type == "client_update": + # updating a client + if "client_id" not in data: + error = "client_id is requried to update." + return json_response({"error": error}, status=400) + elif "client_secret" not in data: + error = "client_secret is required to update." + return json_response({"error": error}, status=400) + + client = Client.query.filter_by( + id=data["client_id"], + secret=data["client_secret"] + ).first() + + if client is None: + error = "Unauthorized." + return json_response({"error": error}, status=403) + + client.application_name = data.get( + "application_name", + client.application_name + ) + + client.application_type = data.get( + "application_type", + client.application_type + ) + + app_name = ("application_type", client.application_name) + if app_name in client_types: + client.application_name = app_name + + elif client_type == "client_associate": + # registering + if "client_id" in data: + error = "Only set client_id for update." + return json_response({"error": error}, status=400) + elif "access_token" in data: + error = "access_token not needed for registration." + return json_response({"error": error}, status=400) + elif "client_secret" in data: + error = "Only set client_secret for update." + return json_response({"error": error}, status=400) + + # generate the client_id and client_secret + client_id = random_string(22) # seems to be what pump uses + client_secret = random_string(43) # again, seems to be what pump uses + expirey = 0 # for now, lets not have it expire + expirey_db = None if expirey == 0 else expirey + application_type = data["application_type"] + + # save it + client = Client( + id=client_id, + secret=client_secret, + expirey=expirey_db, + application_type=application_type, + ) + + else: + error = "Invalid registration type" + return json_response({"error": error}, status=400) + + logo_url = data.get("logo_url", client.logo_url) + if logo_url is not None and not validate_url(logo_url): + error = "Logo URL {0} is not a valid URL.".format(logo_url) + return json_response( + {"error": error}, + status=400 + ) + else: + client.logo_url = logo_url + + client.application_name = data.get("application_name", None) + + contacts = data.get("contacts", None) + if contacts is not None: + if type(contacts) is not unicode: + error = "Contacts must be a string of space-seporated email addresses." + return json_response({"error": error}, status=400) + + contacts = contacts.split() + for contact in contacts: + if not validate_email(contact): + # not a valid email + error = "Email {0} is not a valid email.".format(contact) + return json_response({"error": error}, status=400) + + + client.contacts = contacts + + redirect_uris = data.get("redirect_uris", None) + if redirect_uris is not None: + if type(redirect_uris) is not unicode: + error = "redirect_uris must be space-seporated URLs." + return json_response({"error": error}, status=400) + + redirect_uris = redirect_uris.split() + + for uri in redirect_uris: + if not validate_url(uri): + # not a valid uri + error = "URI {0} is not a valid URI".format(uri) + return json_response({"error": error}, status=400) + + client.redirect_uri = redirect_uris + + + client.save() + + expirey = 0 if client.expirey is None else client.expirey + + return json_response( + { + "client_id": client.id, + "client_secret": client.secret, + "expires_at": expirey, + }) + +@csrf_exempt +def request_token(request): + """ Returns request token """ + try: + data = decode_request(request) + except ValueError: + error = "Could not decode data." + return json_response({"error": error}, status=400) + + if data == "": + error = "Unknown Content-Type" + return json_response({"error": error}, status=400) + + if not data and request.headers: + data = request.headers + + data = dict(data) # mutableifying + + authorization = decode_authorization_header(data) + + if authorization == dict() or u"oauth_consumer_key" not in authorization: + error = "Missing required parameter." + return json_response({"error": error}, status=400) + + # check the client_id + client_id = authorization[u"oauth_consumer_key"] + client = Client.query.filter_by(id=client_id).first() + + if client == None: + # client_id is invalid + error = "Invalid client_id" + return json_response({"error": error}, status=400) + + # make request token and return to client + request_validator = GMGRequestValidator(authorization) + rv = RequestTokenEndpoint(request_validator) + tokens = rv.create_request_token(request, authorization) + + # store the nonce & timestamp before we return back + nonce = authorization[u"oauth_nonce"] + timestamp = authorization[u"oauth_timestamp"] + timestamp = datetime.datetime.fromtimestamp(float(timestamp)) + + nc = NonceTimestamp(nonce=nonce, timestamp=timestamp) + nc.save() + + return form_response(tokens) + +@require_active_login +def authorize(request): + """ Displays a page for user to authorize """ + if request.method == "POST": + return authorize_finish(request) + + _ = pass_to_ugettext + token = request.args.get("oauth_token", None) + if token is None: + # no token supplied, display a html 400 this time + err_msg = _("Must provide an oauth_token.") + return render_400(request, err_msg=err_msg) + + oauth_request = RequestToken.query.filter_by(token=token).first() + if oauth_request is None: + err_msg = _("No request token found.") + return render_400(request, err_msg) + + if oauth_request.used: + return authorize_finish(request) + + if oauth_request.verifier is None: + orequest = GMGRequest(request) + request_validator = GMGRequestValidator() + auth_endpoint = AuthorizationEndpoint(request_validator) + verifier = auth_endpoint.create_verifier(orequest, {}) + oauth_request.verifier = verifier["oauth_verifier"] + + oauth_request.user = request.user.id + oauth_request.save() + + # find client & build context + client = Client.query.filter_by(id=oauth_request.client).first() + + authorize_form = AuthorizeForm(WTFormData({ + "oauth_token": oauth_request.token, + "oauth_verifier": oauth_request.verifier + })) + + context = { + "user": request.user, + "oauth_request": oauth_request, + "client": client, + "authorize_form": authorize_form, + } + + + # AuthorizationEndpoint + return render_to_response( + request, + "mediagoblin/api/authorize.html", + context + ) + + +def authorize_finish(request): + """ Finishes the authorize """ + _ = pass_to_ugettext + token = request.form["oauth_token"] + verifier = request.form["oauth_verifier"] + oauth_request = RequestToken.query.filter_by(token=token, verifier=verifier) + oauth_request = oauth_request.first() + + if oauth_request is None: + # invalid token or verifier + err_msg = _("No request token found.") + return render_400(request, err_msg) + + oauth_request.used = True + oauth_request.updated = datetime.datetime.now() + oauth_request.save() + + if oauth_request.callback == "oob": + # out of bounds + context = {"oauth_request": oauth_request} + return render_to_response( + request, + "mediagoblin/api/oob.html", + context + ) + + # okay we need to redirect them then! + querystring = "?oauth_token={0}&oauth_verifier={1}".format( + oauth_request.token, + oauth_request.verifier + ) + + return redirect( + request, + querystring=querystring, + location=oauth_request.callback + ) + +@csrf_exempt +def access_token(request): + """ Provides an access token based on a valid verifier and request token """ + data = request.headers + + parsed_tokens = decode_authorization_header(data) + + if parsed_tokens == dict() or "oauth_token" not in parsed_tokens: + error = "Missing required parameter." + return json_response({"error": error}, status=400) + + + request.oauth_token = parsed_tokens["oauth_token"] + request_validator = GMGRequestValidator(data) + av = AccessTokenEndpoint(request_validator) + tokens = av.create_access_token(request, {}) + return form_response(tokens) + diff --git a/mediagoblin/plugins/api/__init__.py b/mediagoblin/plugins/api/__init__.py index d3fdf2ef..1eddd9e0 100644 --- a/mediagoblin/plugins/api/__init__.py +++ b/mediagoblin/plugins/api/__init__.py @@ -23,11 +23,11 @@ _log = logging.getLogger(__name__) PLUGIN_DIR = os.path.dirname(__file__) -config = pluginapi.get_config(__name__) - def setup_plugin(): _log.info('Setting up API...') + config = pluginapi.get_config(__name__) + _log.debug('API config: {0}'.format(config)) routes = [ diff --git a/mediagoblin/plugins/api/tools.py b/mediagoblin/plugins/api/tools.py index 92411f4b..d1b3ebb1 100644 --- a/mediagoblin/plugins/api/tools.py +++ b/mediagoblin/plugins/api/tools.py @@ -51,30 +51,6 @@ class Auth(object): def __call__(self, request, *args, **kw): raise NotImplemented() - -def json_response(serializable, _disable_cors=False, *args, **kw): - ''' - Serializes a json objects and returns a werkzeug Response object with the - serialized value as the response body and Content-Type: application/json. - - :param serializable: A json-serializable object - - Any extra arguments and keyword arguments are passed to the - Response.__init__ method. - ''' - response = Response(json.dumps(serializable), *args, content_type='application/json', **kw) - - if not _disable_cors: - cors_headers = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'} - for key, value in cors_headers.iteritems(): - response.headers.set(key, value) - - return response - - def get_entry_serializable(entry, urlgen): ''' Returns a serializable dict() of a MediaEntry instance. diff --git a/mediagoblin/plugins/api/views.py b/mediagoblin/plugins/api/views.py index fde76fe4..69fae7bb 100644 --- a/mediagoblin/plugins/api/views.py +++ b/mediagoblin/plugins/api/views.py @@ -17,17 +17,19 @@ import json import logging -from os.path import splitext -from werkzeug.exceptions import BadRequest, Forbidden +from werkzeug.exceptions import BadRequest from werkzeug.wrappers import Response +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.response import json_response from mediagoblin.decorators import require_active_login from mediagoblin.meddleware.csrf import csrf_exempt -from mediagoblin.media_types import sniff_media -from mediagoblin.plugins.api.tools import api_auth, get_entry_serializable, \ - json_response -from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \ - run_process_media +from mediagoblin.media_types import \ + InvalidFileType, FileTypeNotSupported +from mediagoblin.plugins.api.tools import api_auth, get_entry_serializable +from mediagoblin.submit.lib import \ + check_file_field, submit_media, get_upload_file_limits, \ + FileUploadLimit, UserUploadLimit, UserPastUploadLimit _log = logging.getLogger(__name__) @@ -49,47 +51,46 @@ def post_entry(request): _log.debug('File field not found') raise BadRequest() - media_file = request.files['file'] - - media_type, media_manager = sniff_media(media_file) - - entry = request.db.MediaEntry() - entry.media_type = unicode(media_type) - entry.title = unicode(request.form.get('title') - or splitext(media_file.filename)[0]) - - entry.description = unicode(request.form.get('description')) - entry.license = unicode(request.form.get('license', '')) - - entry.uploader = request.user.id - - entry.generate_slug() - - # queue appropriately - queue_file = prepare_queue_task(request.app, entry, media_file.filename) - - with queue_file: - queue_file.write(request.files['file'].stream.read()) - - # Save now so we have this data before kicking off processing - entry.save() - - if request.form.get('callback_url'): - metadata = request.db.ProcessingMetaData() - metadata.media_entry = entry - metadata.callback_url = unicode(request.form['callback_url']) - metadata.save() - - # Pass off to processing - # - # (... don't change entry after this point to avoid race - # conditions with changes to the document via processing code) - feed_url = request.urlgen( - 'mediagoblin.user_pages.atom_feed', - qualified=True, user=request.user.username) - run_process_media(entry, feed_url) - - return json_response(get_entry_serializable(entry, request.urlgen)) + upload_limit, max_file_size = get_upload_file_limits(request.user) + + callback_url = request.form.get('callback_url') + if callback_url: + callback_url = unicode(callback_url) + try: + entry = submit_media( + mg_app=request.app, user=request.user, + submitted_file=request.files['file'], + filename=request.files['file'].filename, + title=unicode(request.form.get('title')), + description=unicode(request.form.get('description')), + license=unicode(request.form.get('license', '')), + upload_limit=upload_limit, max_file_size=max_file_size, + callback_url=callback_url) + + return json_response(get_entry_serializable(entry, request.urlgen)) + + # Handle upload limit issues + except FileUploadLimit: + raise BadRequest( + _(u'Sorry, the file size is too big.')) + except UserUploadLimit: + raise BadRequest( + _('Sorry, uploading this file will put you over your' + ' upload limit.')) + except UserPastUploadLimit: + raise BadRequest( + _('Sorry, you have reached your upload limit.')) + + except Exception as e: + ''' + This section is intended to catch exceptions raised in + mediagoblin.media_types + ''' + if isinstance(e, InvalidFileType) or \ + isinstance(e, FileTypeNotSupported): + raise BadRequest(unicode(e)) + else: + raise @api_auth diff --git a/mediagoblin/plugins/basic_auth/README.rst b/mediagoblin/plugins/basic_auth/README.rst new file mode 100644 index 00000000..82f247ed --- /dev/null +++ b/mediagoblin/plugins/basic_auth/README.rst @@ -0,0 +1,24 @@ +.. _basic_auth-chapter: + +=================== + basic_auth plugin +=================== + +The basic_auth plugin is enabled by default in mediagoblin.ini. This plugin +provides basic username and password authentication for GNU Mediagoblin. + +This plugin can be enabled alongside :ref:`openid-chapter` and +:ref:`persona-chapter`. + +Set up the basic_auth plugin +============================ + +1. Add the following to your MediaGoblin .ini file in the ``[plugins]`` section:: + + [[mediagoblin.plugins.basic_auth]] + +2. Run:: + + gmg assetlink + + in order to link basic_auth's static assets diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py new file mode 100644 index 00000000..64564c7f --- /dev/null +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -0,0 +1,119 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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 pkg_resources import resource_filename +import os + +from mediagoblin.plugins.basic_auth import forms as auth_forms +from mediagoblin.plugins.basic_auth import tools as auth_tools +from mediagoblin.auth.tools import create_basic_user +from mediagoblin.db.models import User +from mediagoblin.tools import pluginapi +from sqlalchemy import or_ +from mediagoblin.tools.staticdirect import PluginStatic + + +PLUGIN_DIR = os.path.dirname(__file__) + + +def setup_plugin(): + config = pluginapi.get_config('mediagoblin.plugins.basic_auth') + + routes = [ + ('mediagoblin.plugins.basic_auth.edit.pass', + '/edit/password/', + 'mediagoblin.plugins.basic_auth.views:change_pass'), + ('mediagoblin.plugins.basic_auth.forgot_password', + '/auth/forgot_password/', + 'mediagoblin.plugins.basic_auth.views:forgot_password'), + ('mediagoblin.plugins.basic_auth.verify_forgot_password', + '/auth/forgot_password/verify/', + 'mediagoblin.plugins.basic_auth.views:verify_forgot_password')] + + pluginapi.register_routes(routes) + pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates')) + + pluginapi.register_template_hooks( + {'edit_link': 'mediagoblin/plugins/basic_auth/edit_link.html', + 'fp_link': 'mediagoblin/plugins/basic_auth/fp_link.html', + 'fp_head': 'mediagoblin/plugins/basic_auth/fp_head.html', + 'create_account': + 'mediagoblin/plugins/basic_auth/create_account_link.html'}) + + +def get_user(**kwargs): + username = kwargs.pop('username', None) + if username: + user = User.query.filter( + or_( + User.username == username, + User.email == username, + )).first() + return user + + +def create_user(registration_form): + user = get_user(username=registration_form.username.data) + if not user and 'password' in registration_form: + user = create_basic_user(registration_form) + user.pw_hash = gen_password_hash( + registration_form.password.data) + user.save() + return user + + +def get_login_form(request): + return auth_forms.LoginForm(request.form) + + +def get_registration_form(request): + return auth_forms.RegistrationForm(request.form) + + +def gen_password_hash(raw_pass, extra_salt=None): + return auth_tools.bcrypt_gen_password_hash(raw_pass, extra_salt) + + +def check_password(raw_pass, stored_hash, extra_salt=None): + if stored_hash: + return auth_tools.bcrypt_check_password(raw_pass, + stored_hash, extra_salt) + return None + + +def auth(): + return True + + +def append_to_global_context(context): + context['pass_auth'] = True + return context + + +hooks = { + 'setup': setup_plugin, + 'authentication': auth, + 'auth_get_user': get_user, + 'auth_create_user': create_user, + 'auth_get_login_form': get_login_form, + 'auth_get_registration_form': get_registration_form, + 'auth_gen_password_hash': gen_password_hash, + 'auth_check_password': check_password, + 'auth_fake_login_attempt': auth_tools.fake_login_attempt, + 'template_global_context': append_to_global_context, + 'static_setup': lambda: PluginStatic( + 'coreplugin_basic_auth', + resource_filename('mediagoblin.plugins.basic_auth', 'static')) +} diff --git a/mediagoblin/auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py index 33e1f45c..c10496f8 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/plugins/basic_auth/forms.py @@ -13,38 +13,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/>. - import wtforms -from mediagoblin.tools.mail import normalize_email from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ - -def normalize_user_or_email_field(allow_email=True, allow_user=True): - """Check if we were passed a field that matches a username and/or email pattern - - This is useful for fields that can take either a username or email - address. Use the parameters if you want to only allow a username for - instance""" - message = _(u'Invalid User name or email address.') - nomail_msg = _(u"This field does not take email addresses.") - nouser_msg = _(u"This field requires an email address.") - - def _normalize_field(form, field): - email = u'@' in field.data - if email: # normalize email address casing - if not allow_email: - raise wtforms.ValidationError(nomail_msg) - wtforms.validators.Email()(form, field) - field.data = normalize_email(field.data) - else: # lower case user names - if not allow_user: - raise wtforms.ValidationError(nouser_msg) - wtforms.validators.Length(min=3, max=30)(form, field) - wtforms.validators.Regexp(r'^\w+$')(form, field) - field.data = field.data.lower() - if field.data is None: # should not happen, but be cautious anyway - raise wtforms.ValidationError(message) - return _normalize_field +from mediagoblin.auth.tools import normalize_user_or_email_field class RegistrationForm(wtforms.Form): @@ -68,9 +40,10 @@ class LoginForm(wtforms.Form): [wtforms.validators.Required(), normalize_user_or_email_field()]) password = wtforms.PasswordField( - _('Password'), - [wtforms.validators.Required(), - wtforms.validators.Length(min=5, max=1024)]) + _('Password')) + stay_logged_in = wtforms.BooleanField( + label='', + description=_('Stay logged in')) class ForgotPassForm(wtforms.Form): @@ -80,14 +53,24 @@ class ForgotPassForm(wtforms.Form): normalize_user_or_email_field()]) -class ChangePassForm(wtforms.Form): +class ChangeForgotPassForm(wtforms.Form): password = wtforms.PasswordField( 'Password', [wtforms.validators.Required(), wtforms.validators.Length(min=5, max=1024)]) - userid = wtforms.HiddenField( - '', - [wtforms.validators.Required()]) token = wtforms.HiddenField( '', [wtforms.validators.Required()]) + + +class ChangePassForm(wtforms.Form): + old_password = wtforms.PasswordField( + _('Old password'), + [wtforms.validators.Required()], + description=_( + "Enter your old password to prove you own this account.")) + new_password = wtforms.PasswordField( + _('New password'), + [wtforms.validators.Required(), + wtforms.validators.Length(min=6, max=30)], + id="password") diff --git a/mediagoblin/static/js/autofilledin_password.js b/mediagoblin/plugins/basic_auth/static/js/autofilledin_password.js index 45e867fe..45e867fe 100644 --- a/mediagoblin/static/js/autofilledin_password.js +++ b/mediagoblin/plugins/basic_auth/static/js/autofilledin_password.js diff --git a/mediagoblin/templates/mediagoblin/auth/change_fp.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html index 1f7d9aca..47cd591e 100644 --- a/mediagoblin/templates/mediagoblin/auth/change_fp.html +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html @@ -29,16 +29,15 @@ {%- endblock %} {% block mediagoblin_content %} - <form action="{{ request.urlgen('mediagoblin.auth.verify_forgot_password') }}" + <form action="{{ request.urlgen('mediagoblin.plugins.basic_auth.verify_forgot_password') }}" method="POST" enctype="multipart/form-data"> {{ csrf_token }} <div class="form_box"> <h1>{% trans %}Set your new password{% endtrans %}</h1> - {{ wtforms_util.render_divs(cp_form) }} + {{ wtforms_util.render_divs(cp_form, True) }} <div class="form_submit_buttons"> <input type="submit" value="{% trans %}Set password{% endtrans %}" class="button_form"/> </div> </div> - </form> {% endblock %} diff --git a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html new file mode 100644 index 00000000..596a4def --- /dev/null +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_pass.html @@ -0,0 +1,52 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block mediagoblin_head %} + <script type="text/javascript" + src="{{ request.staticdirect('/js/show_password.js') }}"></script> +{% endblock mediagoblin_head %} + +{% block title -%} + {% trans username=user.username -%} + Changing {{ username }}'s password + {%- endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + <form action="{{ request.urlgen('mediagoblin.plugins.basic_auth.edit.pass') }}" + method="POST" enctype="multipart/form-data"> + <div class="form_box edit_box"> + <h1> + {%- trans username=user.username -%} + Changing {{ username }}'s password + {%- endtrans -%} + </h1> + {{ wtforms_util.render_divs(form, True) }} + {{ csrf_token }} + <div class="form_submit_buttons"> + <input type="submit" value="{% trans %}Save{% endtrans %}" + class="button_form" /> + </div> + </div> + </form> +{% endblock %} + + diff --git a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html new file mode 100644 index 00000000..7425630b --- /dev/null +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/create_account_link.html @@ -0,0 +1,27 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block create_account %} + {% if allow_registration %} + <p> + {% trans %}Don't have an account yet?{% endtrans %} + <a href="{{ request.urlgen('mediagoblin.auth.register') }}"> + {%- trans %}Create one here!{% endtrans %}</a> + </p> + {% endif %} +{% endblock %} diff --git a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html new file mode 100644 index 00000000..9fd09ab1 --- /dev/null +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/edit_link.html @@ -0,0 +1,25 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block change_pass_link %} + <p> + <a href="{{ request.urlgen('mediagoblin.plugins.basic_auth.edit.pass') }}"> + {% trans %}Change your password.{% endtrans %} + </a> + </p> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/auth/forgot_password.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html index 46aeddef..b0028ab6 100644 --- a/mediagoblin/templates/mediagoblin/auth/forgot_password.html +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html @@ -24,12 +24,12 @@ {%- endblock %} {% block mediagoblin_content %} - <form action="{{ request.urlgen('mediagoblin.auth.forgot_password') }}" + <form action="{{ request.urlgen('mediagoblin.plugins.basic_auth.forgot_password') }}" method="POST" enctype="multipart/form-data"> {{ csrf_token }} <div class="form_box"> <h1>{% trans %}Recover password{% endtrans %}</h1> - {{ wtforms_util.render_divs(fp_form) }} + {{ wtforms_util.render_divs(fp_form, True) }} <div class="form_submit_buttons"> <input type="submit" value="{% trans %}Send instructions{% endtrans %}" class="button_form"/> </div> diff --git a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_head.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_head.html new file mode 100644 index 00000000..292dce28 --- /dev/null +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_head.html @@ -0,0 +1,20 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +<script type="text/javascript" + src="{{ request.staticdirect('/js/autofilledin_password.js', 'coreplugin_basic_auth') }}"></script> diff --git a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html new file mode 100644 index 00000000..404358d8 --- /dev/null +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_link.html @@ -0,0 +1,25 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block fp_link %} + <p> + <a href="{{ request.urlgen('mediagoblin.plugins.basic_auth.forgot_password') }}" id="forgot_password"> + {% trans %}Forgot your password?{% endtrans %}</a> + </p> +{% endblock %} + diff --git a/mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_verification_email.txt index fb5e1674..fb5e1674 100644 --- a/mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/fp_verification_email.txt diff --git a/mediagoblin/auth/lib.py b/mediagoblin/plugins/basic_auth/tools.py index 8829995a..f943bf39 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/plugins/basic_auth/tools.py @@ -13,14 +13,13 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. - -import random - import bcrypt +import random +from mediagoblin import mg_globals +from mediagoblin.tools.crypto import get_timed_signer_url from mediagoblin.tools.mail import send_email from mediagoblin.tools.template import render_template -from mediagoblin import mg_globals def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): @@ -90,44 +89,9 @@ def fake_login_attempt(): randplus_stored_hash == randplus_hashed_pass -EMAIL_VERIFICATION_TEMPLATE = ( - u"http://{host}{uri}?" - u"userid={userid}&token={verification_key}") - - -def send_verification_email(user, request): - """ - Send the verification email to users to activate their accounts. - - Args: - - user: a user object - - request: the request - """ - rendered_email = render_template( - request, 'mediagoblin/auth/verification_email.txt', - {'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)}) - - # TODO: There is no error handling in place - send_email( - mg_globals.app_config['email_sender_address'], - [user.email], - # TODO - # Due to the distributed nature of GNU MediaGoblin, we should - # find a way to send some additional information about the - # specific GNU MediaGoblin instance in the subject line. For - # example "GNU MediaGoblin @ Wandborg - [...]". - 'GNU MediaGoblin - Verify your email!', - rendered_email) - - EMAIL_FP_VERIFICATION_TEMPLATE = ( - u"http://{host}{uri}?" - u"userid={userid}&token={fp_verification_key}") + u"{uri}?" + u"token={fp_verification_key}") def send_fp_verification_email(user, request): @@ -138,14 +102,16 @@ def send_fp_verification_email(user, request): - user: a user object - request: the request """ + fp_verification_key = get_timed_signer_url('mail_verification_token') \ + .dumps(user.id) + rendered_email = render_template( - request, 'mediagoblin/auth/fp_verification_email.txt', + request, 'mediagoblin/plugins/basic_auth/fp_verification_email.txt', {'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)}) + uri=request.urlgen('mediagoblin.plugins.basic_auth.verify_forgot_password', + qualified=True), + fp_verification_key=fp_verification_key)}) # TODO: There is no error handling in place send_email( diff --git a/mediagoblin/plugins/basic_auth/views.py b/mediagoblin/plugins/basic_auth/views.py new file mode 100644 index 00000000..02d370f0 --- /dev/null +++ b/mediagoblin/plugins/basic_auth/views.py @@ -0,0 +1,223 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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 itsdangerous import BadSignature + +from mediagoblin import messages +from mediagoblin.db.models import User +from mediagoblin.decorators import require_active_login +from mediagoblin.plugins.basic_auth import forms, tools +from mediagoblin.tools.crypto import get_timed_signer_url +from mediagoblin.tools.mail import email_debug_message +from mediagoblin.tools.response import redirect, render_to_response, render_404 +from mediagoblin.tools.translate import pass_to_ugettext as _ + + +def forgot_password(request): + """ + Forgot password view + + Sends an email with an url to renew forgotten password. + Use GET querystring parameter 'username' to pre-populate the input field + """ + fp_form = forms.ForgotPassForm(request.form, + username=request.args.get('username')) + + if not (request.method == 'POST' and fp_form.validate()): + # Either GET request, or invalid form submitted. Display the template + return render_to_response(request, + 'mediagoblin/plugins/basic_auth/forgot_password.html', + {'fp_form': fp_form}) + + # If we are here: method == POST and form is valid. username casing + # has been sanitized. Store if a user was found by email. We should + # not reveal if the operation was successful then as we don't want to + # leak if an email address exists in the system. + found_by_email = '@' in fp_form.username.data + + if found_by_email: + user = User.query.filter_by( + email=fp_form.username.data).first() + # Don't reveal success in case the lookup happened by email address. + success_message = _("If that email address (case sensitive!) is " + "registered an email has been sent with " + "instructions on how to change your password.") + + else: # found by username + user = User.query.filter_by( + username=fp_form.username.data).first() + + if user is None: + messages.add_message(request, + messages.WARNING, + _("Couldn't find someone with that username.")) + return redirect(request, 'mediagoblin.auth.forgot_password') + + success_message = _("An email has been sent with instructions " + "on how to change your password.") + + if user and user.has_privilege(u'active') is False: + # Don't send reminder because user is inactive or has no verified email + messages.add_message(request, + messages.WARNING, + _("Could not send password recovery email as your username is in" + "active or your account's email address has not been verified.")) + + return redirect(request, 'mediagoblin.user_pages.user_home', + user=user.username) + + # SUCCESS. Send reminder and return to login page + if user: + email_debug_message(request) + tools.send_fp_verification_email(user, request) + + messages.add_message(request, messages.INFO, success_message) + return redirect(request, 'mediagoblin.auth.login') + + +def verify_forgot_password(request): + """ + Check the forgot-password verification and possibly let the user + change their password because of it. + """ + # get form data variables, and specifically check for presence of token + formdata = _process_for_token(request) + if not formdata['has_token']: + return render_404(request) + + formdata_vars = formdata['vars'] + + # Catch error if token is faked or expired + try: + token = get_timed_signer_url("mail_verification_token") \ + .loads(formdata_vars['token'], max_age=10*24*3600) + except BadSignature: + messages.add_message( + request, + messages.ERROR, + _('The verification key or user id is incorrect.')) + + return redirect( + request, + 'index') + + # check if it's a valid user id + user = User.query.filter_by(id=int(token)).first() + + # no user in db + if not user: + messages.add_message( + request, messages.ERROR, + _('The user id is incorrect.')) + return redirect( + request, 'index') + + # check if user active and has email verified + if user.has_privilege(u'active'): + cp_form = forms.ChangeForgotPassForm(formdata_vars) + + if request.method == 'POST' and cp_form.validate(): + user.pw_hash = tools.bcrypt_gen_password_hash( + cp_form.password.data) + user.save() + + messages.add_message( + request, + messages.INFO, + _("You can now log in using your new password.")) + return redirect(request, 'mediagoblin.auth.login') + else: + return render_to_response( + request, + 'mediagoblin/plugins/basic_auth/change_fp.html', + {'cp_form': cp_form}) + + ## Commenting this out temporarily because I'm checking into + ## what's going on with user.email_verified. + ## + ## ... if this commit lasts long enough for anyone but me (cwebber) to + ## notice it, they should pester me to remove this or remove it + ## themselves ;) + # + # if not user.email_verified: + # messages.add_message( + # request, messages.ERROR, + # _('You need to verify your email before you can reset your' + # ' password.')) + + if not user.status == 'active': + messages.add_message( + request, messages.ERROR, + _('You are no longer an active user. Please contact the system' + ' admin to reactivate your account.')) + + return redirect( + request, 'index') + + +def _process_for_token(request): + """ + Checks for tokens in formdata without prior knowledge of request method + + For now, returns whether the userid and token formdata variables exist, and + the formdata variables in a hash. Perhaps an object is warranted? + """ + # retrieve the formdata variables + if request.method == 'GET': + formdata_vars = request.GET + else: + formdata_vars = request.form + + formdata = { + 'vars': formdata_vars, + 'has_token': 'token' in formdata_vars} + + return formdata + + +@require_active_login +def change_pass(request): + form = forms.ChangePassForm(request.form) + user = request.user + + if request.method == 'POST' and form.validate(): + + if not tools.bcrypt_check_password( + form.old_password.data, user.pw_hash): + form.old_password.errors.append( + _('Wrong password')) + + return render_to_response( + request, + 'mediagoblin/plugins/basic_auth/change_pass.html', + {'form': form, + 'user': user}) + + # Password matches + user.pw_hash = tools.bcrypt_gen_password_hash( + form.new_password.data) + user.save() + + messages.add_message( + request, messages.SUCCESS, + _('Your password was changed successfully')) + + return redirect(request, 'mediagoblin.edit.account') + + return render_to_response( + request, + 'mediagoblin/plugins/basic_auth/change_pass.html', + {'form': form, + 'user': user}) diff --git a/mediagoblin/plugins/httpapiauth/__init__.py b/mediagoblin/plugins/httpapiauth/__init__.py index 081b590e..2b2d593c 100644 --- a/mediagoblin/plugins/httpapiauth/__init__.py +++ b/mediagoblin/plugins/httpapiauth/__init__.py @@ -15,10 +15,10 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import logging -import base64 -from werkzeug.exceptions import BadRequest, Unauthorized +from werkzeug.exceptions import Unauthorized +from mediagoblin.auth.tools import check_login_simple from mediagoblin.plugins.api.tools import Auth _log = logging.getLogger(__name__) @@ -40,10 +40,10 @@ class HTTPAuth(Auth): if not request.authorization: return False - user = request.db.User.query.filter_by( - username=unicode(request.authorization['username'])).first() + user = check_login_simple(unicode(request.authorization['username']), + request.authorization['password']) - if user.check_login(request.authorization['password']): + if user: request.user = user return True else: diff --git a/mediagoblin/plugins/ldap/README.rst b/mediagoblin/plugins/ldap/README.rst new file mode 100644 index 00000000..ea9a34b3 --- /dev/null +++ b/mediagoblin/plugins/ldap/README.rst @@ -0,0 +1,64 @@ +.. MediaGoblin Documentation + + Written in 2012 by MediaGoblin contributors + + To the extent possible under law, the author(s) have dedicated all + copyright and related and neighboring rights to this software to + the public domain worldwide. This software is distributed without + any warranty. + + You should have received a copy of the CC0 Public Domain + Dedication along with this software. If not, see + <http://creativecommons.org/publicdomain/zero/1.0/>. + +.. _ldap-plugin: + +============= + ldap plugin +============= + +.. Warning:: + This plugin is not compatible with the other authentication plugins. + +This plugin allow your GNU Mediagoblin instance to authenticate against an +LDAP server. + +Set up the ldap plugin +====================== + +1. Install the ``python-ldap`` package. + +2. Add the following to your MediaGoblin .ini file in the ``[plugins]`` section:: + + [[mediagoblin.plugins.ldap]] + +Configuring the ldap plugin +=========================== + +This plugin allows you to use multiple ldap servers for authentication. + +In order to configure a server, add the following to you MediaGoblin .ini file +under the ldap plugin:: + + [[mediagoblin.plugins.ldap]] + [[[server1]]] + LDAP_SERVER_URI = 'ldap://ldap.testathon.net:389' + LDAP_USER_DN_TEMPLATE = 'cn={username},ou=users,dc=testathon,dc=net' + [[[server2]]] + ... + +Make any necessary changes to the above to work with your sever. Make sure +``{username}`` is where the username should be in LDAP_USER_DN_TEMPLATE. + +If you would like to fetch the users email from the ldap server upon account +registration, add ``LDAP_SEARCH_BASE = 'ou=users,dc=testathon,dc=net'`` and +``EMAIL_SEARCH_FIELD = 'mail'`` under you server configuration in your +MediaGoblin .ini file. + +.. Warning:: + By default, this plugin provides no encryption when communicating with the + ldap servers. If you would like to use an SSL connection, change + LDAP_SERVER_URI to use ``ldaps://`` and whichever port you use. Default ldap + port for SSL connections is 636. If you would like to use a TLS connection, + add ``LDAP_START_TLS = 'true'`` under your server configuration in your + MediaGoblin .ini file. diff --git a/mediagoblin/plugins/ldap/__init__.py b/mediagoblin/plugins/ldap/__init__.py new file mode 100644 index 00000000..4673acee --- /dev/null +++ b/mediagoblin/plugins/ldap/__init__.py @@ -0,0 +1,59 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import os + +from mediagoblin.auth.tools import create_basic_user +from mediagoblin.tools import pluginapi + +PLUGIN_DIR = os.path.dirname(__file__) + + +def setup_plugin(): + config = pluginapi.get_config('mediagoblin.plugins.ldap') + + routes = [ + ('mediagoblin.plugins.ldap.register', + '/auth/ldap/register/', + 'mediagoblin.plugins.ldap.views:register'), + ('mediagoblin.plugins.ldap.login', + '/auth/ldap/login/', + 'mediagoblin.plugins.ldap.views:login')] + + pluginapi.register_routes(routes) + pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates')) + + pluginapi.register_template_hooks( + {'create_account': 'mediagoblin/plugins/ldap/create_account_link.html'}) + + +def create_user(register_form): + if 'username' in register_form and 'password' not in register_form: + return create_basic_user(register_form) + + +def no_pass_redirect(): + return 'ldap' + + +def auth(): + return True + +hooks = { + 'setup': setup_plugin, + 'authentication': auth, + 'auth_no_pass_redirect': no_pass_redirect, + 'auth_create_user': create_user, +} diff --git a/mediagoblin/plugins/ldap/forms.py b/mediagoblin/plugins/ldap/forms.py new file mode 100644 index 00000000..7ec1479e --- /dev/null +++ b/mediagoblin/plugins/ldap/forms.py @@ -0,0 +1,40 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import wtforms + +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.auth.tools import normalize_user_or_email_field + + +class RegisterForm(wtforms.Form): + username = wtforms.HiddenField( + '', + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_email=False)]) + email = wtforms.TextField( + _('Email address'), + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_user=False)]) + + +class LoginForm(wtforms.Form): + username = wtforms.TextField( + _('Username'), + [wtforms.validators.Required(), + normalize_user_or_email_field()]) + password = wtforms.PasswordField( + _('Password'), + [wtforms.validators.Required()]) diff --git a/mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html b/mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html new file mode 100644 index 00000000..947e4ae2 --- /dev/null +++ b/mediagoblin/plugins/ldap/templates/mediagoblin/plugins/ldap/create_account_link.html @@ -0,0 +1,25 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block create_account %} + {% if allow_registration %} + <p> + {% trans %}Sign in to create an account!{% endtrans %} + </p> + {% endif %} +{% endblock %} diff --git a/mediagoblin/plugins/ldap/tools.py b/mediagoblin/plugins/ldap/tools.py new file mode 100644 index 00000000..1c436792 --- /dev/null +++ b/mediagoblin/plugins/ldap/tools.py @@ -0,0 +1,65 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import ldap +import logging + +from mediagoblin.tools import pluginapi + +_log = logging.getLogger(__name__) + + +class LDAP(object): + def __init__(self): + self.ldap_settings = pluginapi.get_config('mediagoblin.plugins.ldap') + + def _connect(self, server): + _log.info('Connecting to {0}.'.format(server['LDAP_SERVER_URI'])) + self.conn = ldap.initialize(server['LDAP_SERVER_URI']) + + if server['LDAP_START_TLS'] == 'true': + _log.info('Initiating TLS') + self.conn.start_tls_s() + + def _get_email(self, server, username): + try: + results = self.conn.search_s(server['LDAP_SEARCH_BASE'], + ldap.SCOPE_SUBTREE, 'uid={0}' + .format(username), + [server['EMAIL_SEARCH_FIELD']]) + + email = results[0][1][server['EMAIL_SEARCH_FIELD']][0] + except KeyError: + email = None + + return email + + def login(self, username, password): + for k, v in self.ldap_settings.iteritems(): + try: + self._connect(v) + user_dn = v['LDAP_USER_DN_TEMPLATE'].format(username=username) + self.conn.simple_bind_s(user_dn, password.encode('utf8')) + email = self._get_email(v, username) + return username, email + + except ldap.LDAPError, e: + _log.info(e) + + finally: + _log.info('Unbinding {0}.'.format(v['LDAP_SERVER_URI'])) + self.conn.unbind() + + return False, None diff --git a/mediagoblin/plugins/ldap/views.py b/mediagoblin/plugins/ldap/views.py new file mode 100644 index 00000000..aef1bf56 --- /dev/null +++ b/mediagoblin/plugins/ldap/views.py @@ -0,0 +1,104 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +from mediagoblin import mg_globals, messages +from mediagoblin.auth.tools import register_user +from mediagoblin.db.models import User +from mediagoblin.decorators import allow_registration, auth_enabled +from mediagoblin.plugins.ldap import forms +from mediagoblin.plugins.ldap.tools import LDAP +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.response import redirect, render_to_response + + +@auth_enabled +def login(request): + login_form = forms.LoginForm(request.form) + + login_failed = False + + if request.method == 'POST' and login_form.validate(): + l = LDAP() + username, email = l.login(login_form.username.data, + login_form.password.data) + + if username: + user = User.query.filter_by( + username=username).first() + + if user: + # set up login in session + request.session['user_id'] = unicode(user.id) + request.session.save() + + if request.form.get('next'): + return redirect(request, location=request.form['next']) + else: + return redirect(request, "index") + else: + if not mg_globals.app.auth: + messages.add_message( + request, + messages.WARNING, + _('Sorry, authentication is disabled on this ' + 'instance.')) + return redirect(request, 'index') + + register_form = forms.RegisterForm(username=username, + email=email) + + return render_to_response( + request, + 'mediagoblin/auth/register.html', + {'register_form': register_form, + 'post_url': request.urlgen('mediagoblin.plugins.ldap.register')}) + + login_failed = True + + return render_to_response( + request, + 'mediagoblin/auth/login.html', + {'login_form': login_form, + 'next': request.GET.get('next') or request.form.get('next'), + 'login_failed': login_failed, + 'post_url': request.urlgen('mediagoblin.plugins.ldap.login'), + 'allow_registration': mg_globals.app_config["allow_registration"]}) + + +@allow_registration +@auth_enabled +def register(request): + if request.method == 'GET': + return redirect( + request, + 'mediagoblin.plugins.ldap.login') + + register_form = forms.RegisterForm(request.form) + + if register_form.validate(): + user = register_user(request, register_form) + + if user: + # redirect the user to their homepage... there will be a + # message waiting for them to verify their email + return redirect( + request, 'mediagoblin.user_pages.user_home', + user=user.username) + + return render_to_response( + request, + 'mediagoblin/auth/register.html', + {'register_form': register_form, + 'post_url': request.urlgen('mediagoblin.plugins.ldap.register')}) diff --git a/mediagoblin/plugins/oauth/__init__.py b/mediagoblin/plugins/oauth/__init__.py index 5762379d..82c1f380 100644 --- a/mediagoblin/plugins/oauth/__init__.py +++ b/mediagoblin/plugins/oauth/__init__.py @@ -35,22 +35,22 @@ def setup_plugin(): routes = [ ('mediagoblin.plugins.oauth.authorize', - '/oauth/authorize', + '/oauth-2/authorize', 'mediagoblin.plugins.oauth.views:authorize'), ('mediagoblin.plugins.oauth.authorize_client', - '/oauth/client/authorize', + '/oauth-2/client/authorize', 'mediagoblin.plugins.oauth.views:authorize_client'), ('mediagoblin.plugins.oauth.access_token', - '/oauth/access_token', + '/oauth-2/access_token', 'mediagoblin.plugins.oauth.views:access_token'), ('mediagoblin.plugins.oauth.list_connections', - '/oauth/client/connections', + '/oauth-2/client/connections', 'mediagoblin.plugins.oauth.views:list_connections'), ('mediagoblin.plugins.oauth.register_client', - '/oauth/client/register', + '/oauth-2/client/register', 'mediagoblin.plugins.oauth.views:register_client'), ('mediagoblin.plugins.oauth.list_clients', - '/oauth/client/list', + '/oauth-2/client/list', 'mediagoblin.plugins.oauth.views:list_clients')] pluginapi.register_routes(routes) diff --git a/mediagoblin/plugins/oauth/tools.py b/mediagoblin/plugins/oauth/tools.py index 27ff32b4..af0a3305 100644 --- a/mediagoblin/plugins/oauth/tools.py +++ b/mediagoblin/plugins/oauth/tools.py @@ -23,7 +23,7 @@ from datetime import datetime from functools import wraps -from mediagoblin.plugins.api.tools import json_response +from mediagoblin.tools.response import json_response def require_client_auth(controller): diff --git a/mediagoblin/plugins/oauth/views.py b/mediagoblin/plugins/oauth/views.py index d6fd314f..de637d6b 100644 --- a/mediagoblin/plugins/oauth/views.py +++ b/mediagoblin/plugins/oauth/views.py @@ -21,7 +21,7 @@ from urllib import urlencode from werkzeug.exceptions import BadRequest -from mediagoblin.tools.response import render_to_response, redirect +from mediagoblin.tools.response import render_to_response, redirect, json_response from mediagoblin.decorators import require_active_login from mediagoblin.messages import add_message, SUCCESS from mediagoblin.tools.translate import pass_to_ugettext as _ @@ -31,7 +31,6 @@ from mediagoblin.plugins.oauth.forms import ClientRegistrationForm, \ AuthorizationForm from mediagoblin.plugins.oauth.tools import require_client_auth, \ create_token -from mediagoblin.plugins.api.tools import json_response _log = logging.getLogger(__name__) diff --git a/mediagoblin/plugins/openid/README.rst b/mediagoblin/plugins/openid/README.rst new file mode 100644 index 00000000..870a2b58 --- /dev/null +++ b/mediagoblin/plugins/openid/README.rst @@ -0,0 +1,34 @@ +.. _openid-chapter: + +=================== + openid plugin +=================== + +The openid plugin allows user to login to your GNU Mediagoblin instance using +their openid url. + +This plugin can be enabled alongside :ref:`basic_auth-chapter` and +:ref:`persona-chapter`. + +.. note:: + When :ref:`basic_auth-chapter` is enabled alongside this openid plugin, and + a user creates an account using their openid. If they would like to add a + password to their account, they can use the forgot password feature to do + so. + + +Set up the openid plugin +============================ + +1. Install the ``python-openid`` package. + +2. Add the following to your MediaGoblin .ini file in the ``[plugins]`` section:: + + [[mediagoblin.plugins.openid]] + +3. Run:: + + gmg dbupdate + + in order to create and apply migrations to any database tables that the + plugin requires. diff --git a/mediagoblin/plugins/openid/__init__.py b/mediagoblin/plugins/openid/__init__.py new file mode 100644 index 00000000..ca17a7e8 --- /dev/null +++ b/mediagoblin/plugins/openid/__init__.py @@ -0,0 +1,125 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import os +import uuid + +from sqlalchemy import or_ + +from mediagoblin.auth.tools import create_basic_user +from mediagoblin.db.models import User +from mediagoblin.plugins.openid.models import OpenIDUserURL +from mediagoblin.tools import pluginapi +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ + +PLUGIN_DIR = os.path.dirname(__file__) + + +def setup_plugin(): + config = pluginapi.get_config('mediagoblin.plugins.openid') + + routes = [ + ('mediagoblin.plugins.openid.register', + '/auth/openid/register/', + 'mediagoblin.plugins.openid.views:register'), + ('mediagoblin.plugins.openid.login', + '/auth/openid/login/', + 'mediagoblin.plugins.openid.views:login'), + ('mediagoblin.plugins.openid.finish_login', + '/auth/openid/login/finish/', + 'mediagoblin.plugins.openid.views:finish_login'), + ('mediagoblin.plugins.openid.edit', + '/edit/openid/', + 'mediagoblin.plugins.openid.views:start_edit'), + ('mediagoblin.plugins.openid.finish_edit', + '/edit/openid/finish/', + 'mediagoblin.plugins.openid.views:finish_edit'), + ('mediagoblin.plugins.openid.delete', + '/edit/openid/delete/', + 'mediagoblin.plugins.openid.views:delete_openid'), + ('mediagoblin.plugins.openid.finish_delete', + '/edit/openid/delete/finish/', + 'mediagoblin.plugins.openid.views:finish_delete')] + + pluginapi.register_routes(routes) + pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates')) + + pluginapi.register_template_hooks( + {'register_link': 'mediagoblin/plugins/openid/register_link.html', + 'login_link': 'mediagoblin/plugins/openid/login_link.html', + 'edit_link': 'mediagoblin/plugins/openid/edit_link.html'}) + + +def create_user(register_form): + if 'openid' in register_form: + username = register_form.username.data + user = User.query.filter( + or_( + User.username == username, + User.email == username, + )).first() + + if not user: + user = create_basic_user(register_form) + + new_entry = OpenIDUserURL() + new_entry.openid_url = register_form.openid.data + new_entry.user_id = user.id + new_entry.save() + + return user + + +def extra_validation(register_form): + openid = register_form.openid.data if 'openid' in \ + register_form else None + if openid: + openid_url_exists = OpenIDUserURL.query.filter_by( + openid_url=openid + ).count() + + extra_validation_passes = True + + if openid_url_exists: + register_form.openid.errors.append( + _('Sorry, an account is already registered to that OpenID.')) + extra_validation_passes = False + + return extra_validation_passes + + +def no_pass_redirect(): + return 'openid' + + +def add_to_form_context(context): + context['openid_link'] = True + return context + + +def Auth(): + return True + +hooks = { + 'setup': setup_plugin, + 'authentication': Auth, + 'auth_extra_validation': extra_validation, + 'auth_create_user': create_user, + 'auth_no_pass_redirect': no_pass_redirect, + ('mediagoblin.auth.register', + 'mediagoblin/auth/register.html'): add_to_form_context, + ('mediagoblin.auth.login', + 'mediagoblin/auth/login.html'): add_to_form_context +} diff --git a/mediagoblin/plugins/openid/forms.py b/mediagoblin/plugins/openid/forms.py new file mode 100644 index 00000000..f26024bd --- /dev/null +++ b/mediagoblin/plugins/openid/forms.py @@ -0,0 +1,41 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import wtforms + +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.auth.tools import normalize_user_or_email_field + + +class RegistrationForm(wtforms.Form): + openid = wtforms.HiddenField( + '', + [wtforms.validators.Required()]) + username = wtforms.TextField( + _('Username'), + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_email=False)]) + email = wtforms.TextField( + _('Email address'), + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_user=False)]) + + +class LoginForm(wtforms.Form): + openid = wtforms.TextField( + _('OpenID'), + [wtforms.validators.Required(), + # Can openid's only be urls? + wtforms.validators.URL(message='Please enter a valid url.')]) diff --git a/mediagoblin/plugins/openid/models.py b/mediagoblin/plugins/openid/models.py new file mode 100644 index 00000000..6773f0ad --- /dev/null +++ b/mediagoblin/plugins/openid/models.py @@ -0,0 +1,65 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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 sqlalchemy import Column, Integer, Unicode, ForeignKey +from sqlalchemy.orm import relationship, backref + +from mediagoblin.db.models import User +from mediagoblin.db.base import Base + + +class OpenIDUserURL(Base): + __tablename__ = "openid__user_urls" + + id = Column(Integer, primary_key=True) + openid_url = Column(Unicode, nullable=False) + user_id = Column(Integer, ForeignKey(User.id), nullable=False) + + # OpenID's are owned by their user, so do the full thing. + user = relationship(User, backref=backref('openid_urls', + cascade='all, delete-orphan')) + + +# OpenID Store Models +class Nonce(Base): + __tablename__ = "openid__nonce" + + server_url = Column(Unicode, primary_key=True) + timestamp = Column(Integer, primary_key=True) + salt = Column(Unicode, primary_key=True) + + def __unicode__(self): + return u'Nonce: %r, %r' % (self.server_url, self.salt) + + +class Association(Base): + __tablename__ = "openid__association" + + server_url = Column(Unicode, primary_key=True) + handle = Column(Unicode, primary_key=True) + secret = Column(Unicode) + issued = Column(Integer) + lifetime = Column(Integer) + assoc_type = Column(Unicode) + + def __unicode__(self): + return u'Association: %r, %r' % (self.server_url, self.handle) + + +MODELS = [ + OpenIDUserURL, + Nonce, + Association +] diff --git a/mediagoblin/plugins/openid/store.py b/mediagoblin/plugins/openid/store.py new file mode 100644 index 00000000..8f9a7012 --- /dev/null +++ b/mediagoblin/plugins/openid/store.py @@ -0,0 +1,127 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import base64 +import time + +from openid.association import Association as OIDAssociation +from openid.store.interface import OpenIDStore +from openid.store import nonce + +from mediagoblin.plugins.openid.models import Association, Nonce + + +class SQLAlchemyOpenIDStore(OpenIDStore): + def __init__(self): + self.max_nonce_age = 6 * 60 * 60 + + def storeAssociation(self, server_url, association): + assoc = Association.query.filter_by( + server_url=server_url, handle=association.handle + ).first() + + if not assoc: + assoc = Association() + assoc.server_url = unicode(server_url) + assoc.handle = association.handle + + # django uses base64 encoding, python-openid uses a blob field for + # secret + assoc.secret = unicode(base64.encodestring(association.secret)) + assoc.issued = association.issued + assoc.lifetime = association.lifetime + assoc.assoc_type = association.assoc_type + assoc.save() + + def getAssociation(self, server_url, handle=None): + assocs = [] + if handle is not None: + assocs = Association.query.filter_by( + server_url=server_url, handle=handle + ) + else: + assocs = Association.query.filter_by( + server_url=server_url + ) + + if assocs.count() == 0: + return None + else: + associations = [] + for assoc in assocs: + association = OIDAssociation( + assoc.handle, base64.decodestring(assoc.secret), + assoc.issued, assoc.lifetime, assoc.assoc_type + ) + if association.getExpiresIn() == 0: + assoc.delete() + else: + associations.append((association.issued, association)) + + if not associations: + return None + associations.sort() + return associations[-1][1] + + def removeAssociation(self, server_url, handle): + assocs = Association.query.filter_by( + server_url=server_url, handle=handle + ).first() + + assoc_exists = True if assocs else False + for assoc in assocs: + assoc.delete() + return assoc_exists + + def useNonce(self, server_url, timestamp, salt): + if abs(timestamp - time.time()) > nonce.SKEW: + return False + + ononce = Nonce.query.filter_by( + server_url=server_url, + timestamp=timestamp, + salt=salt + ).first() + + if ononce: + return False + else: + ononce = Nonce() + ononce.server_url = server_url + ononce.timestamp = timestamp + ononce.salt = salt + ononce.save() + return True + + def cleanupNonces(self, _now=None): + if _now is None: + _now = int(time.time()) + expired = Nonce.query.filter( + Nonce.timestamp < (_now - nonce.SKEW) + ) + count = expired.count() + for each in expired: + each.delete() + return count + + def cleanupAssociations(self): + now = int(time.time()) + assoc = Association.query.all() + count = 0 + for each in assoc: + if (each.lifetime + each.issued) <= now: + each.delete() + count = count + 1 + return count diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html new file mode 100644 index 00000000..8d308c81 --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html @@ -0,0 +1,44 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans %}Add an OpenID{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + <form action="{{ request.urlgen('mediagoblin.plugins.openid.edit') }}" + method="POST" enctype="multipart/form-data"> + {{ csrf_token }} + <div class="form_box"> + <h1>{% trans %}Add an OpenID{% endtrans %}</h1> + <p> + <a href="{{ request.urlgen('mediagoblin.plugins.openid.delete') }}"> + {% trans %}Delete an OpenID{% endtrans %} + </a> + </p> + {{ wtforms_util.render_divs(form, True) }} + <div class="form_submit_buttons"> + <input type="submit" value="{% trans %}Add{% endtrans %}" class="button_form"/> + </div> + </div> + </form> +{% endblock %} + diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html new file mode 100644 index 00000000..84301b9e --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html @@ -0,0 +1,43 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans %}Delete an OpenID{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + <form action="{{ request.urlgen('mediagoblin.plugins.openid.delete') }}" + method="POST" enctype="multipart/form-data"> + {{ csrf_token }} + <div class="form_box"> + <h1>{% trans %}Delete an OpenID{% endtrans %}</h1> + <p> + <a href="{{ request.urlgen('mediagoblin.plugins.openid.edit') }}"> + {% trans %}Add an OpenID{% endtrans %} + </a> + </p> + {{ wtforms_util.render_divs(form, True) }} + <div class="form_submit_buttons"> + <input type="submit" value="{% trans %}Delete{% endtrans %}" class="button_form"/> + </div> + </div> + </form> +{% endblock %} diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html new file mode 100644 index 00000000..88b232f8 --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html @@ -0,0 +1,24 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block openid_edit_link %} + <a href="{{ request.urlgen('mediagoblin.plugins.openid.edit') }}"> + {% trans %}OpenID's{% endtrans %} + </a> + · +{% endblock %} diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html new file mode 100644 index 00000000..193a3b2d --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html @@ -0,0 +1,66 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block mediagoblin_head %} + {{ super() }} + {% template_hook("fp_head") %} +{% endblock %} + +{% block title -%} + {% trans %}Log in{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + <form action="{{ post_url }}" + method="POST" enctype="multipart/form-data"> + {{ csrf_token }} + <div class="form_box"> + <h1>{% trans %}Log in{% endtrans %}</h1> + {% if login_failed %} + <div class="form_field_error"> + {% trans %}Logging in failed!{% endtrans %} + </div> + {% endif %} + {% if allow_registration %} + <p> + {% trans %}Log in to create an account!{% endtrans %} + </p> + {% endif %} + {% template_hook('login_link') %} + {% if pass_auth is defined %} + <p> + <a href="{{ request.urlgen('mediagoblin.auth.login') }}?{{ request.query_string }}"> + {%- trans %}Or login with a password!{% endtrans %} + </a> + </p> + {% endif %} + {{ wtforms_util.render_divs(login_form, True) }} + <div class="form_submit_buttons"> + <input type="submit" value="{% trans %}Log in{% endtrans %}" class="button_form"/> + </div> + {% if next %} + <input type="hidden" name="next" value="{{ next }}" class="button_form" + style="display: none;"/> + {% endif %} + </div> + </form> +{% endblock %} + diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html new file mode 100644 index 00000000..fa4d5e85 --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html @@ -0,0 +1,27 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block openid_login_link %} + {% if openid_link is defined %} + <p> + <a href="{{ request.urlgen('mediagoblin.plugins.openid.login') }}?{{ request.query_string }}"> + {%- trans %}Or login with OpenID!{% endtrans %} + </a> + </p> + {% endif %} +{% endblock %} diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html new file mode 100644 index 00000000..9bccb4d8 --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html @@ -0,0 +1,27 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block openid_register_link %} + {% if openid_link is defined %} + <p> + <a href="{{ request.urlgen('mediagoblin.plugins.openid.login') }}"> + {%- trans %}Or register with OpenID!{% endtrans %} + </a> + </p> + {% endif %} +{% endblock %} diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html new file mode 100644 index 00000000..68d028d0 --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html @@ -0,0 +1,24 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% block mediagoblin_content %} + <div onload="document.getElementById('openid_message').submit()"> + {{ html|safe }} + </div> +{% endblock %} diff --git a/mediagoblin/plugins/openid/views.py b/mediagoblin/plugins/openid/views.py new file mode 100644 index 00000000..bb2de7ab --- /dev/null +++ b/mediagoblin/plugins/openid/views.py @@ -0,0 +1,404 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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 openid.consumer import consumer +from openid.consumer.discover import DiscoveryFailure +from openid.extensions.sreg import SRegRequest, SRegResponse + +from mediagoblin import mg_globals, messages +from mediagoblin.db.models import User +from mediagoblin.decorators import (auth_enabled, allow_registration, + require_active_login) +from mediagoblin.tools.response import redirect, render_to_response +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.plugins.openid import forms as auth_forms +from mediagoblin.plugins.openid.models import OpenIDUserURL +from mediagoblin.plugins.openid.store import SQLAlchemyOpenIDStore +from mediagoblin.auth.tools import register_user + + +def _start_verification(request, form, return_to, sreg=True): + """ + Start OpenID Verification. + + Returns False if verification fails, otherwise, will return either a + redirect or render_to_response object + """ + openid_url = form.openid.data + c = consumer.Consumer(request.session, SQLAlchemyOpenIDStore()) + + # Try to discover provider + try: + auth_request = c.begin(openid_url) + except DiscoveryFailure: + # Discovery failed, return to login page + form.openid.errors.append( + _('Sorry, the OpenID server could not be found')) + + return False + + host = 'http://' + request.host + + if sreg: + # Ask provider for email and nickname + auth_request.addExtension(SRegRequest(required=['email', 'nickname'])) + + # Do we even need this? + if auth_request is None: + form.openid.errors.append( + _('No OpenID service was found for %s' % openid_url)) + + elif auth_request.shouldSendRedirect(): + # Begin the authentication process as a HTTP redirect + redirect_url = auth_request.redirectURL( + host, return_to) + + return redirect( + request, location=redirect_url) + + else: + # Send request as POST + form_html = auth_request.htmlMarkup( + host, host + return_to, + # Is this necessary? + form_tag_attrs={'id': 'openid_message'}) + + # Beware: this renders a template whose content is a form + # and some javascript to submit it upon page load. Non-JS + # users will have to click the form submit button to + # initiate OpenID authentication. + return render_to_response( + request, + 'mediagoblin/plugins/openid/request_form.html', + {'html': form_html}) + + return False + + +def _finish_verification(request): + """ + Complete OpenID Verification Process. + + If the verification failed, will return false, otherwise, will return + the response + """ + c = consumer.Consumer(request.session, SQLAlchemyOpenIDStore()) + + # Check the response from the provider + response = c.complete(request.args, request.base_url) + if response.status == consumer.FAILURE: + messages.add_message( + request, + messages.WARNING, + _('Verification of %s failed: %s' % + (response.getDisplayIdentifier(), response.message))) + + elif response.status == consumer.SUCCESS: + # Verification was successfull + return response + + elif response.status == consumer.CANCEL: + # Verification canceled + messages.add_message( + request, + messages.WARNING, + _('Verification cancelled')) + + return False + + +def _response_email(response): + """ Gets the email from the OpenID providers response""" + sreg_response = SRegResponse.fromSuccessResponse(response) + if sreg_response and 'email' in sreg_response: + return sreg_response.data['email'] + return None + + +def _response_nickname(response): + """ Gets the nickname from the OpenID providers response""" + sreg_response = SRegResponse.fromSuccessResponse(response) + if sreg_response and 'nickname' in sreg_response: + return sreg_response.data['nickname'] + return None + + +@auth_enabled +def login(request): + """OpenID Login View""" + login_form = auth_forms.LoginForm(request.form) + allow_registration = mg_globals.app_config["allow_registration"] + + # Can't store next in request.GET because of redirects to OpenID provider + # Store it in the session + next = request.GET.get('next') + request.session['next'] = next + + login_failed = False + + if request.method == 'POST' and login_form.validate(): + return_to = request.urlgen( + 'mediagoblin.plugins.openid.finish_login') + + success = _start_verification(request, login_form, return_to) + + if success: + return success + + login_failed = True + + return render_to_response( + request, + 'mediagoblin/plugins/openid/login.html', + {'login_form': login_form, + 'next': request.session.get('next'), + 'login_failed': login_failed, + 'post_url': request.urlgen('mediagoblin.plugins.openid.login'), + 'allow_registration': allow_registration}) + + +@auth_enabled +def finish_login(request): + """Complete OpenID Login Process""" + response = _finish_verification(request) + + if not response: + # Verification failed, redirect to login page. + return redirect(request, 'mediagoblin.plugins.openid.login') + + # Verification was successfull + query = OpenIDUserURL.query.filter_by( + openid_url=response.identity_url, + ).first() + user = query.user if query else None + + if user: + # Set up login in session + request.session['user_id'] = unicode(user.id) + request.session.save() + + if request.session.get('next'): + return redirect(request, location=request.session.pop('next')) + else: + return redirect(request, "index") + else: + # No user, need to register + if not mg_globals.app_config['allow_registration']: + messages.add_message( + request, + messages.WARNING, + _('Sorry, registration is disabled on this instance.')) + return redirect(request, 'index') + + # Get email and nickname from response + email = _response_email(response) + username = _response_nickname(response) + + register_form = auth_forms.RegistrationForm(request.form, + openid=response.identity_url, + email=email, + username=username) + return render_to_response( + request, + 'mediagoblin/auth/register.html', + {'register_form': register_form, + 'post_url': request.urlgen('mediagoblin.plugins.openid.register')}) + + +@allow_registration +@auth_enabled +def register(request): + """OpenID Registration View""" + if request.method == 'GET': + # Need to connect to openid provider before registering a user to + # get the users openid url. If method is 'GET', then this page was + # acessed without logging in first. + return redirect(request, 'mediagoblin.plugins.openid.login') + + register_form = auth_forms.RegistrationForm(request.form) + + if register_form.validate(): + user = register_user(request, register_form) + + if user: + # redirect the user to their homepage... there will be a + # message waiting for them to verify their email + return redirect( + request, 'mediagoblin.user_pages.user_home', + user=user.username) + + return render_to_response( + request, + 'mediagoblin/auth/register.html', + {'register_form': register_form, + 'post_url': request.urlgen('mediagoblin.plugins.openid.register')}) + + +@require_active_login +def start_edit(request): + """Starts the process of adding an openid url to a users account""" + form = auth_forms.LoginForm(request.form) + + if request.method == 'POST' and form.validate(): + query = OpenIDUserURL.query.filter_by( + openid_url=form.openid.data + ).first() + user = query.user if query else None + + if not user: + return_to = request.urlgen('mediagoblin.plugins.openid.finish_edit') + success = _start_verification(request, form, return_to, False) + + if success: + return success + else: + form.openid.errors.append( + _('Sorry, an account is already registered to that OpenID.')) + + return render_to_response( + request, + 'mediagoblin/plugins/openid/add.html', + {'form': form, + 'post_url': request.urlgen('mediagoblin.plugins.openid.edit')}) + + +@require_active_login +def finish_edit(request): + """Finishes the process of adding an openid url to a user""" + response = _finish_verification(request) + + if not response: + # Verification failed, redirect to add openid page. + return redirect(request, 'mediagoblin.plugins.openid.edit') + + # Verification was successfull + query = OpenIDUserURL.query.filter_by( + openid_url=response.identity_url, + ).first() + user_exists = query.user if query else None + + if user_exists: + # user exists with that openid url, redirect back to edit page + messages.add_message( + request, + messages.WARNING, + _('Sorry, an account is already registered to that OpenID.')) + return redirect(request, 'mediagoblin.plugins.openid.edit') + + else: + # Save openid to user + user = User.query.filter_by( + id=request.session['user_id'] + ).first() + + new_entry = OpenIDUserURL() + new_entry.openid_url = response.identity_url + new_entry.user_id = user.id + new_entry.save() + + messages.add_message( + request, + messages.SUCCESS, + _('Your OpenID url was saved successfully.')) + + return redirect(request, 'mediagoblin.edit.account') + + +@require_active_login +def delete_openid(request): + """View to remove an openid from a users account""" + form = auth_forms.LoginForm(request.form) + + if request.method == 'POST' and form.validate(): + # Check if a user has this openid + query = OpenIDUserURL.query.filter_by( + openid_url=form.openid.data + ) + user = query.first().user if query.first() else None + + if user and user.id == int(request.session['user_id']): + count = len(user.openid_urls) + if not count > 1 and not user.pw_hash: + # Make sure the user has a pw or another OpenID + messages.add_message( + request, + messages.WARNING, + _("You can't delete your only OpenID URL unless you" + " have a password set")) + elif user: + # There is a user, but not the same user who is logged in + form.openid.errors.append( + _('That OpenID is not registered to this account.')) + + if not form.errors and not request.session.get('messages'): + # Okay to continue with deleting openid + return_to = request.urlgen( + 'mediagoblin.plugins.openid.finish_delete') + success = _start_verification(request, form, return_to, False) + + if success: + return success + + return render_to_response( + request, + 'mediagoblin/plugins/openid/delete.html', + {'form': form, + 'post_url': request.urlgen('mediagoblin.plugins.openid.delete')}) + + +@require_active_login +def finish_delete(request): + """Finishes the deletion of an OpenID from an user's account""" + response = _finish_verification(request) + + if not response: + # Verification failed, redirect to delete openid page. + return redirect(request, 'mediagoblin.plugins.openid.delete') + + query = OpenIDUserURL.query.filter_by( + openid_url=response.identity_url + ) + user = query.first().user if query.first() else None + + # Need to check this again because of generic openid urls such as google's + if user and user.id == int(request.session['user_id']): + count = len(user.openid_urls) + if count > 1 or user.pw_hash: + # User has more then one openid or also has a password. + query.first().delete() + + messages.add_message( + request, + messages.SUCCESS, + _('OpenID was successfully removed.')) + + return redirect(request, 'mediagoblin.edit.account') + + elif not count > 1: + messages.add_message( + request, + messages.WARNING, + _("You can't delete your only OpenID URL unless you have a " + "password set")) + + return redirect(request, 'mediagoblin.plugins.openid.delete') + + else: + messages.add_message( + request, + messages.WARNING, + _('That OpenID is not registered to this account.')) + + return redirect(request, 'mediagoblin.plugins.openid.delete') diff --git a/mediagoblin/plugins/persona/README.rst b/mediagoblin/plugins/persona/README.rst new file mode 100644 index 00000000..ef19ac5d --- /dev/null +++ b/mediagoblin/plugins/persona/README.rst @@ -0,0 +1,41 @@ +.. _persona-chapter: + +================ + persona plugin +================ + +The persona plugin allows users to login to you GNU MediaGoblin instance using +`Mozilla Persona`_. + +This plugin can be enabled alongside :ref:`openid-chapter` and +:ref:`basic_auth-chapter`. + +.. note:: + When :ref:`basic_auth-chapter` is enabled alongside this persona plugin, and + a user creates an account using their persona. If they would like to add a + password to their account, they can use the forgot password feature to do + so. + +.. _Mozilla Persona: https://www.mozilla.org/en-US/persona/ + +Set up the persona plugin +========================= + +1. Install the ``requests`` package. + +2. Add the following to your MediaGoblin .ini file in the ``[plugins]`` section:: + + [[mediagoblin.plugins.persona]] + +3. Run:: + + gmg dbupdate + + in order to create and apply migrations to any database tables that the + plugin requires. + +4. Run:: + + gmg assetlink + + in order to persona's static assets. diff --git a/mediagoblin/plugins/persona/__init__.py b/mediagoblin/plugins/persona/__init__.py new file mode 100644 index 00000000..700c18e2 --- /dev/null +++ b/mediagoblin/plugins/persona/__init__.py @@ -0,0 +1,116 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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 pkg_resources import resource_filename +import os + +from sqlalchemy import or_ + +from mediagoblin.auth.tools import create_basic_user +from mediagoblin.db.models import User +from mediagoblin.plugins.persona.models import PersonaUserEmails +from mediagoblin.tools import pluginapi +from mediagoblin.tools.staticdirect import PluginStatic +from mediagoblin.tools.translate import pass_to_ugettext as _ + +PLUGIN_DIR = os.path.dirname(__file__) + + +def setup_plugin(): + config = pluginapi.get_config('mediagoblin.plugins.persona') + + routes = [ + ('mediagoblin.plugins.persona.login', + '/auth/persona/login/', + 'mediagoblin.plugins.persona.views:login'), + ('mediagoblin.plugins.persona.register', + '/auth/persona/register/', + 'mediagoblin.plugins.persona.views:register'), + ('mediagoblin.plugins.persona.edit', + '/edit/persona/', + 'mediagoblin.plugins.persona.views:edit'), + ('mediagoblin.plugins.persona.add', + '/edit/persona/add/', + 'mediagoblin.plugins.persona.views:add')] + + pluginapi.register_routes(routes) + pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates')) + pluginapi.register_template_hooks( + {'persona_end': 'mediagoblin/plugins/persona/persona_js_end.html', + 'persona_form': 'mediagoblin/plugins/persona/persona.html', + 'edit_link': 'mediagoblin/plugins/persona/edit_link.html', + 'login_link': 'mediagoblin/plugins/persona/login_link.html', + 'register_link': 'mediagoblin/plugins/persona/register_link.html'}) + + +def create_user(register_form): + if 'persona_email' in register_form: + username = register_form.username.data + user = User.query.filter( + or_( + User.username == username, + User.email == username, + )).first() + + if not user: + user = create_basic_user(register_form) + + new_entry = PersonaUserEmails() + new_entry.persona_email = register_form.persona_email.data + new_entry.user_id = user.id + new_entry.save() + + return user + + +def extra_validation(register_form): + persona_email = register_form.persona_email.data if 'persona_email' in \ + register_form else None + if persona_email: + persona_email_exists = PersonaUserEmails.query.filter_by( + persona_email=persona_email + ).count() + + extra_validation_passes = True + + if persona_email_exists: + register_form.persona_email.errors.append( + _('Sorry, an account is already registered to that Persona' + ' email.')) + extra_validation_passes = False + + return extra_validation_passes + + +def Auth(): + return True + + +def add_to_global_context(context): + if len(pluginapi.hook_runall('authentication')) == 1: + context['persona_auth'] = True + context['persona'] = True + return context + +hooks = { + 'setup': setup_plugin, + 'authentication': Auth, + 'auth_extra_validation': extra_validation, + 'auth_create_user': create_user, + 'template_global_context': add_to_global_context, + 'static_setup': lambda: PluginStatic( + 'coreplugin_persona', + resource_filename('mediagoblin.plugins.persona', 'static')) +} diff --git a/mediagoblin/plugins/persona/forms.py b/mediagoblin/plugins/persona/forms.py new file mode 100644 index 00000000..608be0c7 --- /dev/null +++ b/mediagoblin/plugins/persona/forms.py @@ -0,0 +1,41 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import wtforms + +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.auth.tools import normalize_user_or_email_field + + +class RegistrationForm(wtforms.Form): + username = wtforms.TextField( + _('Username'), + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_email=False)]) + email = wtforms.TextField( + _('Email address'), + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_user=False)]) + persona_email = wtforms.HiddenField( + '', + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_user=False)]) + + +class EditForm(wtforms.Form): + email = wtforms.TextField( + _('Email address'), + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_user=False)]) diff --git a/mediagoblin/plugins/persona/models.py b/mediagoblin/plugins/persona/models.py new file mode 100644 index 00000000..ff3c525a --- /dev/null +++ b/mediagoblin/plugins/persona/models.py @@ -0,0 +1,36 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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 sqlalchemy import Column, Integer, Unicode, ForeignKey +from sqlalchemy.orm import relationship, backref + +from mediagoblin.db.models import User +from mediagoblin.db.base import Base + + +class PersonaUserEmails(Base): + __tablename__ = "persona__user_emails" + + id = Column(Integer, primary_key=True) + persona_email = Column(Unicode, nullable=False) + user_id = Column(Integer, ForeignKey(User.id), nullable=False) + + # Persona's are owned by their user, so do the full thing. + user = relationship(User, backref=backref('persona_emails', + cascade='all, delete-orphan')) + +MODELS = [ + PersonaUserEmails +] diff --git a/mediagoblin/plugins/persona/static/js/persona.js b/mediagoblin/plugins/persona/static/js/persona.js new file mode 100644 index 00000000..76a7757a --- /dev/null +++ b/mediagoblin/plugins/persona/static/js/persona.js @@ -0,0 +1,59 @@ +/** + * GNU MediaGoblin -- federated, autonomous media hosting + * Copyright (C) 2011, 2012 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/>. + */ + +$(document).ready(function () { + var requestParams = { + backgroundColor: "#171717", + siteName: "GNU MediaGoblin", + siteLogo: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAA0IklEQVR4XuSYS2gUSRyHq6ofk8kDZXycRTwEcfGgboIgBOMTFoxZ8LYXwcWDd/HoRUFPHvbg47gXQeMugqC7iiIeoht0IeDFg+ID8RBNYpKZ6e4qPyYVu5meBhkmSU9S8PHvamro6v76V93TUuSkHdz3q7z7701Tt6+b0gnr4SfYBptgM6yDEvSADwIq8BUmLK/gDbyE/2AKZjjOdNaxl5tlFXJgcFhJKR1EBAkJ/ZRdlu2wFdwWedcwDi9gDEYRMZoQ41Ei9ulVJWT/3qNSKeUuiEDCDspJOAxroQuSzTQ/5+zfJtL0yBhz4d79kXF7o/iUgL5ZNQlBQokyBOdhIwgIQFmWYm4aInBBwns4i5wbyPi8YhNCAhzSENntnym/we/gJy6KAyp1e5t4olJZaqqMrbYfj7fI+b62iHhsRopC8Gy/DFfhT+b9NHkObS8EAT4yqtRNdK9BH3QnLoTMkuC4BrDkGKEYJUCmZp0Skt6matChBK68lkI2OnJ6TmV4DMeR8W7hXNpdSA/lHJwCDaJBEiCW4PrzFV2tb1ZgGEJVCR0lxGUvaR78YYw5w1I23VZCeGCrfx7c0lbGCcpFWANV8EAmk6AUIMG1aZAyTsjiEh8rIjlhIJBDgnTDZa0KPnyB06Tkik2/YlvnVghvJy53UIiUDUqpO+za2XBpoicVEgqiJkLKHLz8m1hOtSLnsyEzl7JRGEbGB85ZkRqd24Qg5ZiU8no6EfFd6fpGeJDnFlatmGRLyxkKw/D2/Yd/t0yIaoEAZePrwGUrIwAf5PeHqxVR7NbCLxiR9+Yyx84eHd846SlX4C/HcS4N7PnFy1VCBgeOlFzXfWD/WZv654TrGeF3GKFUrd9eTeIiEqRFiShIXTENCv6H3RDat7DlE0IqeilPYG2jxCGiJmQltDBgGSvLrLexMvQi5O2SL1lIcBLfncagBLEMQ4cRxS7dlAxjDORNol1yOSelUnOT4MJr+xlIUOWSJgQZhygjUEwuUwY8u0St5FYhKVGQmZY+eG6M0fZ72KInpN/K6KgXWyjEMppNxtTHCTH1acLu+2GxqfHlclmEYVhL7NzcXK1fqVTE7MysmJycrNVGTWtdP6dUajuKRngFkyXkGWyxMhYnIQvv2/aZMQad9WMKiHD85v9hfyvvPaAsu8o7398+6cbKqburOudWd0tqqZUjSEjI5GD7EUQQPMRgj70MzJhZToPtsZ+xgWcPb8AYPBhsEGDikCwJkBDKoZU6q3N1pa548wl7v7O+dc7qW0F0Xut53qe119Gte+rW7f3f/y/tb39HRxplKUae2IsfBfRtW4vruliWxWmITGR6786dO9FRRMP3qZQrVGtVlFLp+wJUNpulra2Ngf5+FAptDJlMBs/zsG2LTDb7coDLZykFQaDwa/OYUgOyxphNMSi7L5jKuuXmN3Tatr0P6JzrTWVyBts9ezDSCfV9n6Gn99GXb+dEp2HZsmXCEnWK6DG956WXXmL3bpkDAj/AYGjPFrm0bw2hjujMteKHAZP1EuWwzlhlmhm/Qi1s4Cgbx3awlMIPfTJuBqPAdh06OzvZsGED+Xx+1t9DIaqrMR8UgFFgPVCLjX3jvAJyw7V32Llc7ilgy1xVJ2A4hnORdOWVSiWOPbOXX1tzJV8/9gjbr7wiXfkpMAsCUS6XefqppxmfGGegrYe8k+Gqgc2U/Spb+1YT6UgAj4zBoJHJdx0828NzXXkviALGylMxWGUMEKGZrsww6VfYOXKQkl9j0eJFbNu2DcdxaJYoUjSqC4KyIwbj0lizuPE1OEdAxF44MbphfP2cpMzPs5pqZkfKkF2PPMPbNt/CsyMvsd+aYPPmzQuqjBSo44PHefyJx+W9V6zcxhX9Gyh4OfwoxEKJ+kMBSmEri5jluJaL7QojUJaFsuOhbJQBO1FrlrLxwwZ1v8GxiSGOxmOoPMGJqMKmy7aKemtmbxTOY0oE2Eka/52ns1WsTtNu/DpwzxxvSgy4kzk3MJonGGBycpKjz+/j9auv4cj0CI+P7GHxosW0DHQTBgH5QmHWRAwPD/PoI4+yqKWL12+4lvZMUSbUUpYwQWGJXXK9DMoI8AJIPMRWeG4Wy1IYDADaICrLsgU4gkZA3a8ThgGVWoVypcRweZKD1VE6NgwIKCmDURA0lIwmCQEHeF8MxhfOkSGSve21LGsECACXBA3HOzdvKgUg9nbE8zlw4AC61GBL70r6iz30FNswGvLZrKzKqaDKiClRLpUIXUX/0gEGR4coTGmWtPVwy9rtjJenAcQRsC0bjSEMQ3nt2BbGgO24WJaNAmGX6zlYtkMUhvK+BgHTccWWiGNQq1Ypl0s0/DqNoIEC7j3wJLumjnHrrbfOciaUgnrVIgqZKzPApcChX5UhdjiFxGD8oCn9LGI5nDUY6Zc/evQow0NDHBscZH3nUrbE47pNWzAGGqGP2EsUjuOyqmsAY7QAmRvIcixmTmm6Sl53ceXmi7CVzVStgus4Mtme66HRGB3heS6u7aIsW4DxMhmMTDoox8HNeigUfqVGFISoKBTGWNrgeC6hEYDJZXMoECYFYQAGsVsx4MKk5lRRNqepVSy0pllagf8Rg3Hbr7InzilU1vuTFLqZbTf0WTMjBkNc0r1798rrt2y4kZWd/RSyObQBgyHjegJcJpNFoUR1KGWBglBreoqd9BW7BCw34wkIdhRgIo3lOKAjud9zLMRrslxRQY7j4HoeYks8YREK8OsNIj+Sifb9hjBHFoMnLjdhFBGGvjBb7I1S1HxhCuPj4/T19c1ivajzvKZWtuaqrlfFYHwgBuNzL2dPnJfbdgUywF8DNGVtxaNSFmclSilGRkbYv38/fYUObli6lXW9y3FcTybHRuHlMkRRRBD4uI6LI+rHkdUuwZkD2nbQRpMvtKCMASVZS0IdogDluCgMtiX3YdDoyKAyGUJhgI0VRoTCIk2tUqE8PUUo7JV4SGKSqBTJJBtj5DuJp2aEIWRdV0CPf85CopQ4PBLRN821D3w6BuPrMRiTp8MQyVMle+CfTGhmAJVkbWWcLTvENX36aZYWe2Jm3CCrWYyr4+I6joDieBkUELkZwOB5OTHSMUDpVyHQPo7tye8oZaGFWmKsZQVHURgPTRT6oMBxxE4QNurx1SYyAZHtoHVEpTQjrnakQwwy8cIOo8BoQ2QibKXEXdYJ88r1GiYC17JZsmSJgCJqa7ZIXGYlO5GJeADJQr/rtACJwYhiMFYBH2q2Hco6d7vxwAMP0Om18Ipll4BSopoyXkaYICsR8XAEmHjIKlCORRhEhFGAQoGyhAkZ1yWMNMaEoBQqGTqJN3QkqxkbC+VaCMhhRK1SFVUUBGWq1QqlSilRS6GsfEs8NIWoKR0B4DmugOAkjsJ0tcxUvUT/wEDKfBYW0SjUyvPevzNmySeAvWLgT8OG/D2gAZdEHDfdzzg7u3HkyBHQhuuXbqHgZUX/Z92MGGBQANiJfm7UaxgFnpdFN3xhR71RE+NqAL/RAMuiVJ5GGSUgFoqt4poGQQAK8ZoEVNcRdvlG4/vynoBQrZepB0H6DxLwFAhD6lEojNbJd6rUa/LZNV0n0oZao8ZUo8zqvqWnzCIoheS8/Lqi6TYH+HAMxvvT8qJfpbKuAK5sth1KIbt855ARF7d2oKWXZS09YFt4joPt2KIWhBtK4Qe+qJxSZUbcU1BUamUCvyHpjkI2T4SR1xGaWq0q+r6YLxJMTwhzLKPEbji2C7aRla+UEqAaYUOAqge+2INUMKQMlZ8bsUeRTH7DaGFP3feJJIZRlP0aTlue/v7+00rruJ4h9FXz/EXA+2IwPgZMLcQQKe+Mq0VMUsRWJBWDBH+CLuqMs68pnSuVCm/acBWB0WQtN9H1Gq2D1DSIujFoqo06WUDXykzNTKKwsBQ0Al+iZmMMjSCg4fvCjpnytLAQFGBwHU8ms9oIEIfAaGqNBkHoi71BzVIzqdEWEDDI9/KjQIDVWkAlMhoLi+PlSZ4bP8CGSzY3qatTSsqSuVn2f4jZ8YZmlqg5hcYtwFBzzKGUIVc0nIsEvs+/3Xsvv33p68U45jM50ctiCBNXUhsxoNQbdbTRYlfK1Qok+tx1bBRKmKKwZCVb0KTq4oEYcLmKR4QSO6SNMGWeKtWp92QiAh0J8EZA0MKUFIwYbGFHKajx+NheFi1fwuYtW06HHU2gS8CI0aTiJ8Asj8E43syQtL4oiK9vBLxmz8rNcq4iq8+1ZKKSmII0BY5MvutJYs8PGmhtRHVNl8soASMgEM8HsTtGa3ntWJYAYQmYGgwIsFqDTGAISVxjjAyZ1PiaEkmAF9UUGbQR70qYgAEgNeySCT5cGuLAzBArVq8WMFLP6nTFssB2RHWRiIsIHwD+eK7KsgEN/EVytdIPcRzDuYofBLS6OWEHWiO+fBQmkx2SMZGwoOE35CpBV+L/CxOUQoPcr7VMMWFytcX4ChhYGnwTESXxRZQwwDSpT0sJgPK+H4pnha0siU1c28bGoqp9xmqTjDVKDJXHmQ4qLO5ZxXXX3E5nX05AFTBOMz+XMsTLzAIkffO1MRH+IiZEPQWE+EUQ25DLgB4gIAXkPBWx+aLrbVEHQRjJpFhK1I+wQSbZGKarldQIQ2JYMYjIJBqTXCHjuBjLioctyUO/4QtrjAHQGATQVK0k6kkMuvzdE/UZWfmBiQBDQ4fUooAxv0zW9ggiH8/N09LSxU1b3sXqZRfz9N4f4DoZgrBxSru58M+FJZIVbpJLgS0xKE/GOBgnDeFj6t/dxBbg3NmRTsihQ4eYqE2hULIi05Wa6vVqvYqfBHMYw0S1xIxfZrw+TUfbAKXGDNp2GZ0apOjlCXWAY2wKbh4VNsgArdkinuXhODZZO4OdbDZV/JrkxvygxlhtmmPVcerKUIt8CoVOCTB72gfoa1tEX8dSFnWuYMfen1Otl1jatxXHtjk6spu2GBiDolavJGpXzWODbD/PzFAt1+nt6sfOSsKSFB9jEo8rUMzB7JUxBk/EqSrLacqnvHpWRhewHc5J0mCttdiCnQ/wQ1Em4i3ZkptC2NEIQ7TWojIOTI4yEQMxFDZYu+Ja1q28AhGjiXSAMUqALFenqPsl8rl2LB0xNLqXKb9GGDbQ9RLj00OEyeq3nAyrl26jt9hBrjYtTFm++CLaW3rJehlaCm3kcwW0hvsf/yoNv8bNl78TSzloo2gr9rLzwEOMTBxkwOpKc1dpjAXInj3UiyzrupStV13FA4/+ALLT86poLZuF4rk7gb9UStkqMepXA/cBWcACoRbZvDkvhW3Hjx9nfO8xblm+DcnkJmDZyhZmaLETNsPlcZ4bewnV2suNl76VRV3LJVYRaVppQSixQeKuhuIUuLaDSa21iKLhV+Vzs9mcAGowiCNgW8l3EHWG7HuEIUZb/P2//j7vfPUfk81kcVwJVMUZqDeqVGtlvv+Lz3DFtZek2QdGhkfwq4obL389a5ZvxhiEXZ/60ke44srLF/TEgoaUqaYsiQDbGNMeg1tNOXA5kAdMSi3Hk+t5ke7ubob3HILEyIqbKjmpgDCMMBjR5Y+P7mblqmu545q7aIRVIBKdrVCUKlMS+PlBlYybJ59to96oSArdAkBL2hxIrgbHzmHZCkyESjetjAG0AAFK3GVAAsnxmVFuuvyt8n0j0wBjMIBlbCw7Tz7Xwiu3v5NnD3yXnp4+jh48ziuvegvXXX4bM+VJCT6Vcvi3h77JpdsuXhCMlCVKwezgW/36j+/95udTQLY3vwnn7XyG0NrzPHSLRyWoJ6tTAZJKx498LGx2jx+k2LGCO669U1SRMUZW/s6XHuXw0C6W9m1mpnxC1Ev8c2HYuuWXAjrV0zL5pOGhUTSXsCtFAsAslSrgpZPW09XDkkUD6KgBWhgFKnFZLRtjoLe7n67RTXgNm7t/4z/QUiwyOjYK2NRrPj968B9RLdMU3PaXDaItyyQ2Z9ac/zrweZUcqPklsOUkgqKuOI8ikfrQ03u5OtbdtaCRRMESEYu6uO/4M7zmlo+yun9dajN4cud9PPr8T9i+8TUs7b1IGJDNZnAcjzCqcXx0L1vWXYWyJJ91RnZt7u22bQmgRieRe6iTiB6UlaIMBhifnODw4C5WDqyjo62X0YnjPL/3IY5P7WLTpo2ntT1Rn72B1QCs2J57DpAHNjb5y83GfEGUmz2M+aKaeEh6H4VCgaA7G9uIA6wo9kp0HDUVNnS0L2FJ9wCgJCr/t4f/BaMzvOKyd9Lfsw5NiOyPOLbYhZZiAcdR1P0ybS3tGHPy+8gFA6SsWNgVlZ9L0YMSUE3ifh89foA9h57GzvpEBOjI0JlbztoVW2lr74hB6KCQu4qd+x/Dc/K8dOhZ3PYyFw1slEWGUadKOApLtJ4Vk9gxOZY7QDfgpO5AwpDmve9TFqUtLPNdwo0bN7J/916mymU6Mq1C3UpYZW9llFtvvpuO1k60DnnpyIvYVp6L178SZUEm44r+ti2FagK5p6OPSPuJepLv2qyefmUaw3EslCVqTmwaaCzX4zP//IeE1Pj4n32M6667llwux/T0DD+7/xd89u/+iduufTstLW3kcgWODO9BYYEdyn2p13UqMYDlACGppBzcrmLf9zeUUl9LAcEgZzhIPJCpyWkAjh49ghSdtbfLpozjOIyOjnH8+CDValVGX/eyWK9vwXYsvGKEVv6CkeveHS9gTQeU/CozSvP+t3yCQj4DlqFeCbnvsXtY2reF5UvWkc9l8DyL8yXKQlgGiBdlJ/Vejp3lJw99jZ8/8W2+fs9X+bXX3pFOSXI1MSgP8fa3vZsPv+u/Mzx2jC99+0943eVv5sWpfSxe1sIZiLCjXlFzjzX8oaOU2jL3C6NIi8+YPFGhVqmzYeVVkhbPOBmsapGDQ3uYLk3Q1b6U26+9iVtvfBNBWItp/JTsZ+zZ/zzTlQqRqmC7SsplbNsWcNZdsplgyqaQXcRVW18tase2HCrVqmRwDxx7jmsufiPFQhbXUWjDSbUjq9CWEYaRxAyO7cqeh2U7UvSmLGHwgqpWmKEUrivXRMXYjJeGuf/Rb/HpT/7fMRivxRgJYKGpPOjmV97Mx//0D/jkX/5ZbPzXkq+OYmYOMF2fYDFnBIhoB5iX/d3oACtmuV9W6qUYisUixTVF9uw6wKqBTWJAo2S71HM9YUkQRpJKOHr4iKy8ga71EldsXnMV41MjMWiTHBt+KQZnjKHRowR+iOsG3H7N22MwF1P3a+TsDI16IF4KBro7B+jp7CY0NbRGjLmXdZN9dYsTk8c5NnSAYqeNcgN6unvx7YDO9m5KJwzVaYtFfX2JG6pIJVVrnmcnSU9RMTieje3DumVbeN0bbwOiearaknikwXvfdxfat/job3+QdyxxyCzdTvTC18+GqQvJEgdYNdfgCENS9BQsW7mY793/j7EK2YAOBVkkwm4EkhBs+EFaLC0qwHFdPNchX/DoaomNde8KlGWolCrUaoGU5hSKGbSREhqJ3Gs1H8fOsO/I4yzqGsC2IPCTCcy4SdFAnnt/+Q0efeEH/Ml//SPe/Z47ZUJj5hGFoQAwPDTK/T9+mJ2PHWJR91Lx5lI3W4rfLNV0sstKmSMFcBdt3kpXdwdgWEhsYaXPK26/jkJnG1ZLiMn1S93vGUtyAnkOkfscoGvunXNEDNbAyj4++7U/4oqLbmdTHLyVymWQ3E6ViZkRZipTdBU7UVYGXwcUcq0UykWmJqtksi7ZrJPaE/FaGo2I0A8FiDAIASQ6PjE9yJLupemOnvxuDKD8nYee/h7rt7fz3Z8OEgaB3OMlMYljO+SyedraOli/YRN3vfcunt55kKsufpVE2cIKUVEGB4WyZzsorbkeqvUJMl6RIKjhujnAYEw4y6uUBeQ36OpsYTCzlMWNMl1dXZyNqPndC1odoHP2TQt7VD09PbICf/CL/0m1VmOgb52AcO8j/wRGMaAP4OYLhHaRE/WAXOtSyk4HG9fdRnd7L8KeJHDzGyGqXMOYhIkSFxiMirho9Xa62voIogbZrIuX8Xh29yPsH3ya//LxD/Hq219HpTIlwWF+weMCGoXhk5/6a373tz7KkcH9LBtYieEkUzQGC0UiwrADh3dz+2teASBg7Nr1vCzEFSvWpPZERhRFbNq4kVWbNqOmL+L4xB68Nu98HSgsWnBKa5RWnot3tfWSTfzwoS/wo19+gS//rz/FN9PctOWD3LJ2HSs62unPatbnIwYaLxEN/YKXYgMdaZIU+8nADJKrao5tIhZ3r5B0iefaZHIOQ2OH+d7Pv8gn/vYPeeUrbqHRKJPPFyT6X0jSzywUcnziU3/Gz5/8Vlr4ljKUKNCgmhliJN/1zjvfDsC3vvUN7rzzPTEou/nJT36IUu6suVDK4Ybrb+SlwccYa+w6u4NFwAIecs4C3PnBEnMljSWEnlddfSWhNcMlF1/M+vXrGRw9gFI2uWyW9pZWulrj0dYmWdaZ8hiu7QkgWouHdAoeayRwSryrvQd38Du/9wG2bNmSVDNmTnPbVEkwuv6iVYyOH08Skfpk9aEhFUlQrll+kbAOIr785a8IO26++SaeeWYHWvtzXHfF4kVLqHCU3t7epnjtnMU5kzZIKShixLZu3cryFcvE+9gz+DPKLbcyNTOGY0Xkiy20F1vpb28lUpru9h5kV045DI8dlQkw2vxKKhs0tqPRTo3bb3u1pDaEFajTdCuV3L+kv0+Osvl+2By4iYeVslQ8OVeidKmm37NnL48//jgf/vBH+NKX/kkK6Wa70YY1q1dSyBU4z6IsoDGPS+bUoKQxRXdPD3hVdk4aSks/yrBzqdTHYispt5w+sZMv//DjvHjwKe659zPs3P8EtWpAPR5hoFlILEllgO1aaBNQbMmnicB5ti0Mw5dN79i2S3dvK1PTUwkYCpX8Hk09TaJAJwsGUYetrW14XoavfOWrlEozUp0/+28Yuno7yeQyAOfzxHBgAeUzwCMFZdahmauvvZSSeY6nDt7PqH0RY4t+i4rqYn1HnjcuL3JNdpDOke9yU0edK9dej448xGWuhbJS54AhwZu4z7ZNsZiju6sLY+aeUZW6WqampkSnz8EkUVEBJvDoau8jiSmRasfIYDdF/yaJPJUlOTKWL18mgeY3vvE1pqfLAs5sZhr6FvUJy89WFLAAjnULmKBJzhRsqfrQhsXL2lm6PsuBme/y+O4fMtP5BsqBodXRdHcupWvj7zDUcgfPHT7Ik7u/z/DEYYkd/HpAKrZjCQscx8YgG0Ny8NIPgkTVnMyx1WoVvvCFL/K9732fT3/6UwLKQlKr1ZHiN5DIPgZxblAm9mpqtColq8py+f3f/6gw77bb7uCVcXTe2toyh50Wg8cGCcNzY8YCyYTSAoAozlBkEk1ygnXVqlXozBAHRg9TXnwXFWcpkx2/wfef/CGP7/lHhmoPYreP8+zBnzBZHkOHCowwIykCsEFWs1SsyzgxdqLJ0TDCyscee0wOeL73ve/ni1/8x/l+pEGkVJrGD+pgoLnviolIbYgsgIkTVUaPT6Ejn0sv3c6jjz7MPXFO6/Of/2ySqmlGUQuLisVzsyHGqAUB2Qdw9iyZn5Lv7eth95GfMlFpMJx7Iz9+9J/ZHxv+tWtXsXzFAC3FFlauW8TgyGEwVmJLUr2vENFgMCxbshqjdKqn0VrsF88++xz33nt/bHS/yPDwCGNjQ7NUmrKU3Ldly1bx8lBNVtPImQ8g9ZwMmazDkZfGpIhBaz8G5RLe+tY3i1c5X4krYQjq5Pc+GzHzGTJkAUfS9+ffdHbAtLa2MrCqjR2Hvs2juz/PdLiPG2+8kc7OjtRbkeNh1caUMDJhgoCRgoqtUBhast2YyJplyMHhgQceFFDe/e67xGs7Fk8QqDkLRHHZxVfTku1Epe+l+yYGYV/qbRU7sux57pic4g2DMGWEXOdX0iiefvoZ8b7Onh0sJMMWsHseaoZzlo6ODlas7WHjJcu57rrrJFHZvHp379pDT8dSWalJwwDJNYEwA8sSA4yti9Sn3DQ4JRFhxV13vYe7734/QRCSy2VfhrkWkTbzKilNUsMrdsOGQkuWJx55jkcefoxqrSI2ZKGVr3VEGNbYv++gFG+crZelo9kvEWGPBTw+18vS5w6IqItsNisZ4WQiZ9NbGWaqY5ikqkN+nAxlG1AIa4x22PvcqASeTXhI5fng4KCorXXr1rJhw2YgXNC+KWZXEKbRvDHJ+0ahlc9A31q+8uWvypG7SqUsQM91s+v1hiyGhx54AhM5Z+1iaa3mAmKAHRZQmls8JIb23EUmPx1zRDo0DI7uFSAavkEZlcQKJDGBAqPwMjaHdo/h18Om+CfgD/7gY8zMlKRC5Dvf+VdAs5Dkch5Oxm6eCzHiqWhhipHkZECZygmXQ4cPy+ng8fHRNA5BDveUSkxOTvCud3yAnsxWXnXlO2JVeSxl7+nj8fIMeT6NQ15oTp3okAslaYJOVNpMZZJGUBN/vlGPRHejDJEwIz2BpMi1uDzz0H4J9FKgL774Mh566AEeeeQXDAyswJiIhSRb9HAdu8moW4kdEQcBdFL/Gxm6ujpY038Zf/3nn+Mzn/kMR48cF1cZSY3YAsYb3/Qm1ne+ios2bOXqba9iZjwQ5pyJYTdiv2bdb5LmZwespDH9DppE+toqLoSkeR+p9Ks2SrJDaJRhptSgUdOyhWu0GPkk8DQU2zM88rN9c4xbmLDPSv+fhUTZwrpZLe4irQX8KIwA0oBR3lu3+iK2rryFn/9gJx/56H/mg3d/KAbhLdz59vfxtjf8Dleveg+9XUtAzpyUeM0NH+T55144Y+/KmFlgZICfNYe+T9IkykAYXjiGAJJnavhl6dJjlBHD3qhGBHVDlIIRIS5xqlGff3o3SrlnEHgF1BtlKo1pUki0MQKGJBq1kYFBrn4QoYDFPf1sWXU9rdEm6qOdrC2+hjUtv8Zt2++iJdOJJSe/LIg0Ha0dbFv7BoaGhk7bwOv5gAB8sxmQx4EyoAFQ0mT4grZvlUP8OSUeTRQajIJKNaBSDgSYNGgLfSMpFj+s8Xf//TNo3TitJhRS6V6vI9vLo7uSHJxungEBJwhCUUvJW8Ke9vZuli1dyUVrriBrtTA4dpC9h55mcGQ/bsZGtB5ywIhG3Wd08rC0eTrdmCSK1EKA3BOXAblWchzhUWACiJrdMmMuLEtsqSx/gXI5lK3VUBsq9YBGPZRCtTQQNKHF+OQoY8NTDI8MyUZZFPkywS+jFpNKmBpPPfMElsklet5irghjwij5TE29XkUpLdvGbe1FNq7bxtqlF7NpzXYWLxrAWBplG7m/WvUpVaqMTO6Wtk2nK1EITbjZwIsxBjMAVlwGlL71i6b6rLSpMKgLAoiAcf3111Oxd7L74MMMD5cJQoMBJqd9qqVA1IhSlsQE3R19tLnL+dGPfiRAlMtVGg0fPctdMUnCcVI6LOzbt58P/faHKJWn5qqTuTVU8ns6NDy848e8dGQXEjSGobAhW3RwM0j1jG0nbaKwxHV9ds9DrFq79AzU6Hwv1hhzT3KNLGlDh7z4K0A1O/NhABgulMgkbNywEdr3snfoPo4PHaFaDQi1ZqYUiOdlkigebdPft5o//tgnePDBhwAjrmnMAik8iF1TcYMnJiYEFNfJxoHj/0mrt4SL110PmFllPSPjh6WAe7azYXFocE8SjSd3qiRWSWqAIx2IS35g8EWU8SjVhiXeOh3boZJuQcqat0B/FKsrFWOhFUDaDCW+DgJLmj8gW9BN9Lqw4IweUfhVh6u3vA7LDmktunhZJylQAKNhYnKcb9z3af70//ovvOH1r5P4QKLxMEKbSLrI/cu/fI1P/PWniAKLO+/4ffp6loLSzU2pYyb8EK1Drr/s9bOYE+lQasQWEHmvmGvnqz/8JK++7k4C3+LhPf9Mz5Li6XW9A2oliznyFHBDPP/VZqOe8v7jzYZGa1FbXFhJ1YfN4pUWkZrCWJGwpN7QBH5EvR4i+yMZS/Jh73vTf+Vv//xr/OeP/DFPPfUMDzz4U779nW/zJ3/05/ze7/4h3/3qE9yw9V1cufkOBhatBhXNqyzYtulmrrnkNfNWtmJO7iphlut4ckL4b/7pP/Kq696GbWeYqgxR8U+c/hMZGvNiD4B7UzAAUqOuY1viGWO+DtSbGwb4jQsPSLMqqfjDBL6Rui5L9DXoUIBJQHEAeMPNdxEML+Vzf/lj/u6/fZ//+bcPcuhZC3+snyVdm4VxW1ZfI4V4mPkUz2XyYkMWLujQaRkS+WyRWr3M/Y99Q1j17tf9ATmvhTDUNII6ruOctu0Ig1mA+IjwCZrEapqUIHnMzz/QLBpCPzXuF16M8jk+ukfsl1JGWGqARiOUbV+dVoxYEb09faxZdjnbNtzGNZfdQbHYSqFQlD38zWsvpVhoQbBWC7JywZ+lXSAKuRaxMd+697Ps2PUIa5dt56bL3yxH34IgIuPl2LP/UToO1jl+fOhU6ko0jZ4fDN4Tk2EiNhUncVigtcaVwM8BLwUMBfmi5sILsulk11Zy9dY3o/DJ5lw8T+FYCsuRfXV0ZMnZkS1rrkPrdG9DkcvksKW+S+Mk9xrM6TBUQKjWy0zOjPHUi/dzdGQvmdaIsAZvfeXHyOdyolaNVsLWatjghfu+QHcEv/QGufzyy/kVIg3NjJ7di1FrvdhxnBM/+rdvhCRiLdAN6DFjzC+AqBnPoHFBWJKuVDm9uv/5XRSO1qiVjkmhRBBFVGs+vq8lhY5WYJSok662ZTz2wv28EK/SA8de4ODxF+LX3+WRZ3/IocEXKVWnxF32nByOlSGXKcpROFt55LMt8joeUr5aq/o8+ux9/PKZ/8VPnvh7fvN9t/LNb32FjRs209+xVaJxMfRGSawCisNHn6Gl7nOsPiEJzpcXmbu5yUQb+Ie4lcnw3H5b6mX6LC6zLOvw3NZ+uYJGWec/r3XixAmGn9nP1a2rcbDZWx1l+bb34GaKWI5FxnMo5mxsR5HxXGGKMRaVaoVao4qFBSj2H9lJ/6YaQ0OjhA0Lv+7T2bqI7p5eBgeP0NLaQkuxjZ0v7pFtgcg0WLduDRsuWh4HkE/RxWWcmDnMzW9ayzVXXcOtN7+ZD/0f/w0gTbVQbzTkyN193/6r+PuuYWf9OMfafC677DJZXPMrdNRC7ZlqwHZg59yucs4Cbf3s2JYcia//j1LqPzSfG/EbFpmcviAsabdz5L0cRsEG08PjT36eTdvvxglsbCtHzYcsFsb42KEtrnCxkKVYzKYJO9bbm3hkxz/zmc/9DVs2b423YN/GscNDvOuDr+W22/5ICuHe+pbf5NrNb2JqZpz9U/fyht+8kW2XbecXP91BaA7T09nPsz+d4l+/9Jd8+N2fplKdSZqkgY6kzSzf/9GneWX7WrSjGLC7OBwdWyDYTBtizvOsFPC1GIgXWUDUKVr8HQHamz/Oy2kc7/wFjFpWnmbowRfZ3rlauoEaSzE9PsGzTsiSlbfTWegik7XJZVvwPI2d7C66rp2e8wAMtuXyxHMPMBrsoF6tsa7vFpb1rOOr9/0Fd//Wu/nO977N8uINLOrtZ3TyGC/ueQrfGufSyy/iyIs+oWnEQeSN9Pctp5DPUamWACthBzLZ93zvT7nSdNLa1goYUaVfH36MQmcrbY5Ndz5LaMB2XbAyeC19ONk8idQBG+iNAZk6NSDzgfkA8FkSOa+qq1lljYxivzjB+vZ+2TxyMi6SApmZ5lC9RK19BUv6NstefSHflRy4gXzOEVBs25IhuKA4cuwArmczsHi1pD9GR0f43Hf+E6+74QNsWLVNomzXzpPLtGCMkorL/kUracm3JkeWjXhSkqYPtSQ/bdvjGz//JBvLARt6V2BkizkUl/yno8/Q7VRpsR1spTAAGEI3g15/DZZtN59Hf1+sgb4QayAVX83ZdLZ+HLi8+X7LMmQL5rwB8uzTz7B5uo3eYideNiM1wjoKZa/ExuLo1DBPNk6wcvnNdLQtERbFJ7ekIDubsbClPawhIzFKkvYQxtjpPjg6kuPZoEzS4iPCoLGUlZYxpdMhYDR8yQDjh5oT4wfYt/d+eisVNvatxMlmMWiq5YrYqecmdtORmcFNupyCkhR9bdXlmGyBJnkgZsZNZ9smNpU3AseABpBJz8c16pDNGYw5d0DK0yXa1CLpg+KZTFoaLin6MAxY1rWEfr+Hh48+yPBkN7lCHxEBflAh6xVpKXTRUeyWvlyOrcQRcByraZItjIqkiZnCSvNaMiKMsIC0f1aoCQKk+ebekWc4vvdR7LFDbO9ZQ7GvD1xbWBwEmnICyIw/Ta8nu4pyUjiby1HuXS1gNDU7KQPvTFq3B2fTSDntozUY0+tNSqlvNbduigKFb51b6780mHK1whCJe5vPayI0jpwX9AgjDx2GWHmLm3IXM1abYKx+gonDDzGKYdPK6wh9X7wf13jScsnySRsCSDmqZSvZEVRoJJ0PEvVjONnCSSsc5eJm8oyVD3Jwz8/JTQyx3ivSvXQLypHuAdKIOQxD2c4tl0qM10soVcax2/GyeckwVNuXUMt3pmBoRPioPA7pPDTjt+TIWBT9LfAh5oiXMzhn+ZiKtInY/p89yaaom1BHtLS209LWQj6fk9Vm2ZZkcjGIaDS2UaAN040yT4y/xLGwRl/Pehb3rGOgd73EF6nH4zkOGkMSO2IrjQbR9dogYPhBxNTMMMdGdzE29ALdfsC1A5sJLYORViBSQYObzSBJ0NFhJqYnicoNHvb3c21HBrdYxPVcwmInk92r556u/VYMxptP50GUitOUG6/7NS/+Uk8AmwE1+9kh+qw7B42NjcGTg/SQlw4P+WyBtvZ2OuLh2BZOxktP32JQCY4Go5O+WZbLTK3EkZlRyjpkJgoIlIXnFWlr6SPMFPCy8cgUsbRm95HHKE0NYbkZelsW0ahMYYV1CrUS61oHyBVaeXByH9ctWk/ByRIFgXRPzWRzGAwzpWkGJwdplEvsK08R2ZNs7W4n11IkzLcz3rU6ZX6qL5+MQdh+us/RVWf4zMKCUmosQT1Dk2TyBts+Y5pI+1i1e4LuuoMf+aKq8tk83R1dOJ4nBXDSrEYMpkaTbnA5WIjKQRmhGsoARlEN6jTqVbFJE/UZfGMY8Ss8WzrAZZkB+nId4ChpO9iaK9Keb5UDpcq1sRXS1P/J0b1c3b2eSqNKm5clkytIe9jR8hiTlTGGYmBG/AkubsvT1t0JhfaYGWvAsprtxmFjzFUxU0fixjKG0xDnDHV+AGwADjFHGlVFJscZP9ilf8kSDry0j6F6C9241KM6UT3EmlRkc3np0ZvxPHEd0/6KKr66yZNwdNpyCQWWEvAKbgHprBBq2sIOaSubLY8z6ndySdcaArS0NM9lM7huPDIetutghIWarkyRWqNOaWJaGp1lihbT1SrVsMREbZJqvcbxcIY1nk2+kCPMFCnFYJAwo8mIvzl2bYcv2EPBjDFBTLsjwBWABsJZoNQUga9Q6sya0izRARV7gnFqgEJFhlK9RLk8LbuC8U4g0zMzlMrl+FqS49XlcplSJb6WypQrFdlDb9QaYnDDIECH0m0UFHi2x97qCJcWlhKhxTDHzCObK8QjK8e4EQ8rpF6pyTNM2qMMB8pDhLUaY9MTjMwMMVGZxK9V2dmYoE+FdLcWMG09zCzeKMxoOlYbAnfEc/WUZHIv/GPzRH1tV0o9DtSAHE1iO5DNaQynlpmxURrPPoUb+gzXNWWToUiRxeQkoec4Lhk7I1G47UnjmeT4wskI3Tr5aAtZ9UhsYREloLi+5t7xF7k6vxKVscnlC9hOfM3l5XO0NgJiGPhShVIulwhLdXaER1nqFNHKCJBWELFLz1CkyqaOFqL+Nfi9K5trVE0Cxk0xGA+nRvyCAxKjrizLUlrr9cDOl2uLmsmfevt3dHSUzPMxIEZTrwVSkzVlYByHJXTQRRHbceUDs44r+ai0EZmFkjSLdHgAAUFpg7Jt8aIUSjyyXdUh8qFNp1cgk8+Sz+UluWjHA4wA5/s+8pi9hi8R+IH6OENMsU61ggELi2FTp2JNsrUtD2suJWzrm5ujKiXMeOgCPXr11I9Diq8blVIPAD1pemDeM6rcl+fKvn37WD54QPoxinG2FGEjIAoMQ9owjk2namHAtOBZOXJJV2zE8QogaZCvlcYyQhUsbPHCbGUT+T479BCbVS84Dq0treTyOYlPSLtYNxpiM8JKgxkr4Fk9yEa6GdQz9JMnBMapELll1nd3YVZfhsnmm+MMCzistX5znFJ/KmXGOQNyDuC0J6BsBcK5zoJlGzI5syBbdjz4czabAMtx0kK1kw+erzeY8X1K2jAdQdEUaVcdeHi04OJgqBPgq5AQLf+FBMKgLFksYzGpy9QI6KaAp7LiVcWACKhSXY+mVq1JlD+iK/JYpU1eH65x2BHtZrFboGZCcpmIruWbiBatApgLxpNa69fGYAyf6/PVnfO0J16LaXpxvDK+Arx9fkZX9gRwM7Oeoy7G061XIJtBEoSijpRkUKU3VrFIplKhzfdZbOBEUGekMUhoHGpGAS4duPSZPBlsIiRWQQBF46kMEYoc8RWNMRH1Wh0hktaANO5HEplRhd2MsI1FtOgMj5rDrC/YuJ7G5Nowq7YRedmFWl5I0Hf7rW9RAKcBxoVnyJxSovcDfwO0zGWLaCQLHE/juLB/zy5ajhyg3XNki1SepOY4oDUqOYUbNnwpCw1D8ZwIwlDOaJggoq4NDQ0loA44WIDCUx4eGU6YKnll027aaMNDYaFAjLSUDhGgjBI27GKcLlxyuJTQtOZbqRRmWLxsLVHHItA67aqQquUy8J9iMP5HDIYXxxk+50EU51HiL6biL2ZiUFYnaftb0l3Hedu2yjC+bwddU8dlovKFPF4mK+kHExkBRI4RRJrQ6MQtFZdWQAmiCCJpUS7xhq1AAShRezIUyDhchzy95IwtsDgo4VJIgINDCZ+daoI24+LgsrhjCf1r1jJVdLHtpCBMWQZoAFngQWPMO2I2HD1Le3HhAZmflJTSoruVUp8CsswXMbyqNoM1tI9coyzpCdtzMUZJeY1rWWhOPt3AhBGT9Qa2MfEQJwBjFmhWJmkVObMhicmnpxtsYRVlAmZMnQYBJRpihyKFMKlPtcRALMJZ3Y/dUgRLsYAExpgPJvsZTnwNSeSCAXIBVFhnosLeAThABFiAkklD1ACEIbnSEPn6NDaarG2jDBhAgzRcDn1f7jtWqWJ8n27XRjmuAPJyMlouUa91scLtwbEcsplMwrCQkhNQUz6VLo9FKzYSOUrYqyCNKTRgAzXga8DvxWyYat7P+HcDCEC6K5YAtBH4CPBeRPABoQOkxlhhDLhhjVxUJxNU8cI6TtiQavO0CbMHPHDoKL22ojOXFUBfjoH7J0ssZg1t0mHIw+lpI8i7BFkHPxtfcyf7eKXVA0opvylX9w/Ap2UPfM6/6d8ZIAursfjaDXwBuAOwT8VSZbQMKwpw/CpeUCdDwMT4CQ6MnWBVxhbjrxBQ0wd1YByP0HIYN1k6iktQxSxkXLAUxrY4Dfm61vp3Y1d2aKFnDv57ByQFRQCIgQnjUqN+y7I+ALwWuISTEgEqHVwYMU3DnlP4fB/wVzEAE69+1VsdrTUxGCHA/16AzH9WYpSAlAO2AK8A3g2s56Q0ElCsdHB2opNhkmuGk7LTGHOPUuqHSZ1UFWCu9/S/MSDzJVUJTVH/bwBvBW4A7PPEFtPEwJ8B39Ra3xOrpGmAU6il/38Bkq5IwFFKmTiWCZqqKJdblnUFsAHYBCxKRitQBHJNwWcI1IASUAaOA8PAXuAZrfWLMQD7m+ImN3kOSCQR9v8H5P8FdKdwLi9BNikAAAAASUVORK5CYII=" + }; + + var signinLink = document.getElementById('persona_login'); + if (signinLink) { + signinLink.onclick = function() { navigator.id.request(requestParams); }; + } + + var signinLink1 = document.getElementById('persona_login1'); + if (signinLink1) { + signinLink1.onclick = function() { navigator.id.request(requestParams); }; + } + + var signoutLink = document.getElementById('logout'); + if (signoutLink) { + signoutLink.onclick = function() { navigator.id.logout(); }; + } + + var logout_url = document.getElementById('_logout_url').value; + var persona_user = document.getElementById('_persona_user').value; + + navigator.id.watch({ + loggedInUser: persona_user || null, + onlogin: function(assertion) { + document.getElementById('_assertion').value = assertion; + document.getElementById('_persona_login').submit(); + }, + onlogout: function() { + $.ajax({ + type: 'GET', + url: logout_url, + success: function(res, status, xhr) { window.location.reload(); }, + error: function(xhr, status, err) { alert("Logout failure: " + err); } + }); + } + }); +}); diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html new file mode 100644 index 00000000..be62b8cc --- /dev/null +++ b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit.html @@ -0,0 +1,43 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans %}Add an OpenID{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + <form action="{{ request.urlgen('mediagoblin.plugins.persona.edit') }}" + method="POST" enctype="multipart/form-data"> + {{ csrf_token }} + <div class="form_box"> + <h1>{% trans %}Delete a Persona email address{% endtrans %}</h1> + <p> + <a href="javascript:;" id="persona_login"> + {% trans %}Add a Persona email address{% endtrans %} + </a> + </p> + {{ wtforms_util.render_divs(form, True) }} + <div class="form_submit_buttons"> + <input type="submit" value="{% trans %}Delete{% endtrans %}" class="button_form"/> + </div> + </div> + </form> +{% endblock %} diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html new file mode 100644 index 00000000..a022c62a --- /dev/null +++ b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/edit_link.html @@ -0,0 +1,24 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block persona_edit_link %} + <a href="{{ request.urlgen('mediagoblin.plugins.persona.edit') }}"> + {% trans %}Persona's{% endtrans %} + </a> + · +{% endblock %} diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html new file mode 100644 index 00000000..975683da --- /dev/null +++ b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/login_link.html @@ -0,0 +1,25 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block person_login_link %} + <p> + <a href="javascript:;" id="persona_login"> + {% trans %}Or login with Persona!{% endtrans %} + </a> + </p> +{% endblock %} diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona.html new file mode 100644 index 00000000..03d63aae --- /dev/null +++ b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona.html @@ -0,0 +1,38 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% block persona %} + <form id="_persona_login" + action= + {%- if edit_persona is defined -%} + "{{ request.urlgen('mediagoblin.plugins.persona.add') }}" + {%- else -%} + "{{ request.urlgen('mediagoblin.plugins.persona.login') }}" + {%- endif %} + method="POST"> + {{ csrf_token }} + <input type="hidden" name="assertion" type="text" id="_assertion"/> + <input type="hidden" name="_logout_url" type="text" id="_logout_url" + value="{{ request.urlgen('mediagoblin.auth.logout') }}"/> + <input type="hidden" type="text" id="_persona_user" + {% if request.session.get('persona_login_email', False) %} + value="{{ request.session['persona_login_email'] }}"/> + {% else %} + value=""/> + {% endif %} + </form> +{% endblock %} diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona_js_end.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona_js_end.html new file mode 100644 index 00000000..8c0d72d5 --- /dev/null +++ b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/persona_js_end.html @@ -0,0 +1,21 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +<script src="https://login.persona.org/include.js"></script> +<script type="text/javascript" + src="{{ request.staticdirect('/js/persona.js', 'coreplugin_persona') }}"></script> diff --git a/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html new file mode 100644 index 00000000..bcd9ae2b --- /dev/null +++ b/mediagoblin/plugins/persona/templates/mediagoblin/plugins/persona/register_link.html @@ -0,0 +1,25 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block persona_register_link %} + <p> + <a href="javascript:;" id="persona_login"> + {% trans %}Or register with Persona!{% endtrans %} + </a> + </p> +{% endblock %} diff --git a/mediagoblin/plugins/persona/views.py b/mediagoblin/plugins/persona/views.py new file mode 100644 index 00000000..1bba3b8c --- /dev/null +++ b/mediagoblin/plugins/persona/views.py @@ -0,0 +1,194 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import json +import logging +import requests + +from werkzeug.exceptions import BadRequest + +from mediagoblin import messages, mg_globals +from mediagoblin.auth.tools import register_user +from mediagoblin.decorators import (auth_enabled, allow_registration, + require_active_login) +from mediagoblin.tools.response import render_to_response, redirect +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.plugins.persona import forms +from mediagoblin.plugins.persona.models import PersonaUserEmails + +_log = logging.getLogger(__name__) + + +def _get_response(request): + if 'assertion' not in request.form: + _log.debug('assertion not in request.form') + raise BadRequest() + + data = {'assertion': request.form['assertion'], + 'audience': request.urlgen('index', qualified=True)} + resp = requests.post('https://verifier.login.persona.org/verify', + data=data, verify=True) + + if resp.ok: + verification_data = json.loads(resp.content) + + if verification_data['status'] == 'okay': + return verification_data['email'] + + return None + + +@auth_enabled +def login(request): + if request.method == 'GET': + return redirect(request, 'mediagoblin.auth.login') + + email = _get_response(request) + if email: + query = PersonaUserEmails.query.filter_by( + persona_email=email + ).first() + user = query.user if query else None + + if user: + request.session['user_id'] = unicode(user.id) + request.session['persona_login_email'] = email + request.session.save() + + return redirect(request, "index") + + else: + if not mg_globals.app.auth: + messages.add_message( + request, + messages.WARNING, + _('Sorry, authentication is disabled on this instance.')) + + return redirect(request, 'index') + + register_form = forms.RegistrationForm(email=email, + persona_email=email) + return render_to_response( + request, + 'mediagoblin/auth/register.html', + {'register_form': register_form, + 'post_url': request.urlgen( + 'mediagoblin.plugins.persona.register')}) + + return redirect(request, 'mediagoblin.auth.login') + + +@allow_registration +@auth_enabled +def register(request): + if request.method == 'GET': + # Need to connect to persona before registering a user. If method is + # 'GET', then this page was acessed without logging in first. + return redirect(request, 'mediagoblin.auth.login') + register_form = forms.RegistrationForm(request.form) + + if register_form.validate(): + user = register_user(request, register_form) + + if user: + # redirect the user to their homepage... there will be a + # message waiting for them to verify their email + return redirect( + request, 'mediagoblin.user_pages.user_home', + user=user.username) + + return render_to_response( + request, + 'mediagoblin/auth/register.html', + {'register_form': register_form, + 'post_url': request.urlgen('mediagoblin.plugins.persona.register')}) + + +@require_active_login +def edit(request): + form = forms.EditForm(request.form) + + if request.method == 'POST' and form.validate(): + query = PersonaUserEmails.query.filter_by( + persona_email=form.email.data) + user = query.first().user if query.first() else None + + if user and user.id == int(request.user.id): + count = len(user.persona_emails) + + if count > 1 or user.pw_hash: + # User has more then one Persona email or also has a password. + query.first().delete() + + messages.add_message( + request, + messages.SUCCESS, + _('The Persona email address was successfully removed.')) + + return redirect(request, 'mediagoblin.edit.account') + + elif not count > 1: + form.email.errors.append( + _("You can't delete your only Persona email address unless" + " you have a password set.")) + + else: + form.email.errors.append( + _('That Persona email address is not registered to this' + ' account.')) + + return render_to_response( + request, + 'mediagoblin/plugins/persona/edit.html', + {'form': form, + 'edit_persona': True}) + + +@require_active_login +def add(request): + if request.method == 'GET': + return redirect(request, 'mediagoblin.plugins.persona.edit') + + email = _get_response(request) + + if email: + query = PersonaUserEmails.query.filter_by( + persona_email=email + ).first() + user_exists = query.user if query else None + + if user_exists: + messages.add_message( + request, + messages.WARNING, + _('Sorry, an account is already registered with that Persona' + ' email address.')) + return redirect(request, 'mediagoblin.plugins.persona.edit') + + else: + # Save the Persona Email to the user + new_entry = PersonaUserEmails() + new_entry.persona_email = email + new_entry.user_id = request.user.id + new_entry.save() + + request.session['persona_login_email'] = email + + messages.add_message( + request, + messages.SUCCESS, + _('Your Persona email address was saved successfully.')) + + return redirect(request, 'mediagoblin.edit.account') diff --git a/mediagoblin/plugins/piwigo/__init__.py b/mediagoblin/plugins/piwigo/__init__.py index 73326e9e..c4da708a 100644 --- a/mediagoblin/plugins/piwigo/__init__.py +++ b/mediagoblin/plugins/piwigo/__init__.py @@ -17,6 +17,8 @@ import logging from mediagoblin.tools import pluginapi +from mediagoblin.tools.session import SessionManager +from .tools import PWGSession _log = logging.getLogger(__name__) @@ -32,6 +34,9 @@ def setup_plugin(): pluginapi.register_routes(routes) + PWGSession.session_manager = SessionManager("pwg_id", "plugins.piwigo") + + hooks = { 'setup': setup_plugin } diff --git a/mediagoblin/plugins/piwigo/forms.py b/mediagoblin/plugins/piwigo/forms.py index 5bb12e62..fb04aa6a 100644 --- a/mediagoblin/plugins/piwigo/forms.py +++ b/mediagoblin/plugins/piwigo/forms.py @@ -26,3 +26,19 @@ class AddSimpleForm(wtforms.Form): # tags = wtforms.FieldList(wtforms.TextField()) category = wtforms.IntegerField() level = wtforms.IntegerField() + + +_md5_validator = wtforms.validators.Regexp(r"^[0-9a-fA-F]{32}$") + + +class AddForm(wtforms.Form): + original_sum = wtforms.TextField(None, + [_md5_validator, + wtforms.validators.Required()]) + thumbnail_sum = wtforms.TextField(None, + [wtforms.validators.Optional(), + _md5_validator]) + file_sum = wtforms.TextField(None, [_md5_validator]) + name = wtforms.TextField() + date_creation = wtforms.TextField() + categories = wtforms.TextField() diff --git a/mediagoblin/plugins/piwigo/tools.py b/mediagoblin/plugins/piwigo/tools.py index 4d2e985a..484ea531 100644 --- a/mediagoblin/plugins/piwigo/tools.py +++ b/mediagoblin/plugins/piwigo/tools.py @@ -14,18 +14,23 @@ # 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 collections import namedtuple import logging import six import lxml.etree as ET -from werkzeug.exceptions import MethodNotAllowed +from werkzeug.exceptions import MethodNotAllowed, BadRequest +from mediagoblin.tools.request import setup_user_in_request from mediagoblin.tools.response import Response _log = logging.getLogger(__name__) +PwgError = namedtuple("PwgError", ["code", "msg"]) + + class PwgNamedArray(list): def __init__(self, l, item_name, as_attrib=()): self.item_name = item_name @@ -73,9 +78,18 @@ def _fill_element(el, data): def response_xml(result): r = ET.Element("rsp") r.set("stat", "ok") - _fill_element(r, result) + status = None + if isinstance(result, PwgError): + r.set("stat", "fail") + err = ET.SubElement(r, "err") + err.set("code", str(result.code)) + err.set("msg", result.msg) + if result.code >= 100 and result.code < 600: + status = result.code + else: + _fill_element(r, result) return Response(ET.tostring(r, encoding="utf-8", xml_declaration=True), - mimetype='text/xml') + mimetype='text/xml', status=status) class CmdTable(object): @@ -106,3 +120,46 @@ class CmdTable(object): _log.warn("Method %s only allowed for POST", cmd_name) raise MethodNotAllowed() return func + + +def check_form(form): + if not form.validate(): + _log.error("form validation failed for form %r", form) + for f in form: + if len(f.errors): + _log.error("Errors for %s: %r", f.name, f.errors) + raise BadRequest() + dump = [] + for f in form: + dump.append("%s=%r" % (f.name, f.data)) + _log.debug("form: %s", " ".join(dump)) + + +class PWGSession(object): + session_manager = None + + def __init__(self, request): + self.request = request + self.in_pwg_session = False + + def __enter__(self): + # Backup old state + self.old_session = self.request.session + self.old_user = self.request.user + # Load piwigo session into state + self.request.session = self.session_manager.load_session_from_cookie( + self.request) + setup_user_in_request(self.request) + self.in_pwg_session = True + return self + + def __exit__(self, *args): + # Restore state + self.request.session = self.old_session + self.request.user = self.old_user + self.in_pwg_session = False + + def save_to_cookie(self, response): + assert self.in_pwg_session + self.session_manager.save_session_to_cookie(self.request.session, + self.request, response) diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index bd3f9320..f913a730 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -20,11 +20,20 @@ import re from werkzeug.exceptions import MethodNotAllowed, BadRequest, NotImplemented from werkzeug.wrappers import BaseResponse -from mediagoblin import mg_globals +from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.meddleware.csrf import csrf_exempt -from mediagoblin.submit.lib import check_file_field -from .tools import CmdTable, PwgNamedArray, response_xml -from .forms import AddSimpleForm +from mediagoblin.auth.tools import check_login_simple +from mediagoblin.submit.lib import \ + submit_media, check_file_field, get_upload_file_limits, \ + FileUploadLimit, UserUploadLimit, UserPastUploadLimit + + +from mediagoblin.user_pages.lib import add_media_to_collection +from mediagoblin.db.models import Collection + +from .tools import CmdTable, response_xml, check_form, \ + PWGSession, PwgNamedArray, PwgError +from .forms import AddSimpleForm, AddForm _log = logging.getLogger(__name__) @@ -34,13 +43,18 @@ _log = logging.getLogger(__name__) def pwg_login(request): username = request.form.get("username") password = request.form.get("password") - _log.info("Login for %r/%r...", username, password) + user = check_login_simple(username, password) + if not user: + return PwgError(999, 'Invalid username/password') + request.session["user_id"] = user.id + request.session.save() return True @CmdTable("pwg.session.logout") def pwg_logout(request): _log.info("Logout") + request.session.delete() return True @@ -51,14 +65,30 @@ def pwg_getversion(request): @CmdTable("pwg.session.getStatus") def pwg_session_getStatus(request): - return {'username': "fake_user"} + if request.user: + username = request.user.username + else: + username = "guest" + return {'username': username} @CmdTable("pwg.categories.getList") def pwg_categories_getList(request): - catlist = ({'id': -29711, + catlist = [{'id': -29711, 'uppercats': "-29711", - 'name': "All my images"},) + 'name': "All my images"}] + + if request.user: + collections = Collection.query.filter_by( + get_creator=request.user).order_by(Collection.title) + + for c in collections: + catlist.append({'id': c.id, + 'uppercats': str(c.id), + 'name': c.title, + 'comment': c.description + }) + return { 'categories': PwgNamedArray( catlist, @@ -90,16 +120,51 @@ def pwg_images_addSimple(request): dump = [] for f in form: dump.append("%s=%r" % (f.name, f.data)) - _log.info("addimple: %r %s %r", request.form, " ".join(dump), request.files) + _log.info("addSimple: %r %s %r", request.form, " ".join(dump), + request.files) if not check_file_field(request, 'image'): raise BadRequest() - return {'image_id': 123456, 'url': ''} + upload_limit, max_file_size = get_upload_file_limits(request.user) + + try: + entry = submit_media( + mg_app=request.app, user=request.user, + submitted_file=request.files['image'], + filename=request.files['image'].filename, + title=unicode(form.name.data), + description=unicode(form.comment.data), + upload_limit=upload_limit, max_file_size=max_file_size) + + collection_id = form.category.data + if collection_id > 0: + collection = Collection.query.get(collection_id) + if collection is not None and collection.creator == request.user.id: + add_media_to_collection(collection, entry, "") + + return { + 'image_id': entry.id, + 'url': entry.url_for_self( + request.urlgen, + qualified=True)} + + # Handle upload limit issues + except FileUploadLimit: + raise BadRequest( + _(u'Sorry, the file size is too big.')) + except UserUploadLimit: + raise BadRequest( + _('Sorry, uploading this file will put you over your' + ' upload limit.')) + except UserPastUploadLimit: + raise BadRequest( + _('Sorry, you have reached your upload limit.')) + - md5sum_matcher = re.compile(r"^[0-9a-fA-F]{32}$") + def fetch_md5(request, parm_name, optional_parm=False): val = request.form.get(parm_name) if (val is None) and (not optional_parm): @@ -133,17 +198,13 @@ def pwg_images_addChunk(request): return True -def possibly_add_cookie(request, response): - # TODO: We should only add a *real* cookie, if - # authenticated. And if there is no cookie already. - if True: - response.set_cookie( - 'pwg_id', - "some_fake_for_now", - path=request.environ['SCRIPT_NAME'], - domain=mg_globals.app_config.get('csrf_cookie_domain'), - secure=(request.scheme.lower() == 'https'), - httponly=True) +@CmdTable("pwg.images.add", True) +def pwg_images_add(request): + _log.info("add: %r", request.form) + form = AddForm(request.form) + check_form(form) + + return {'image_id': 123456, 'url': ''} @csrf_exempt @@ -158,13 +219,13 @@ def ws_php(request): request.args, request.form) raise NotImplemented() - result = func(request) - - if isinstance(result, BaseResponse): - return result + with PWGSession(request) as session: + result = func(request) - response = response_xml(result) + if isinstance(result, BaseResponse): + return result - possibly_add_cookie(request, response) + response = response_xml(result) + session.save_to_cookie(response) - return response + return response diff --git a/mediagoblin/processing/__init__.py b/mediagoblin/processing/__init__.py index f3a85940..102fd5de 100644 --- a/mediagoblin/processing/__init__.py +++ b/mediagoblin/processing/__init__.py @@ -14,12 +14,20 @@ # 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/>. +# Use an ordered dict if we can. If not, we'll just use a normal dict +# later. +try: + from collections import OrderedDict +except: + OrderedDict = None + import logging import os -from mediagoblin.db.util import atomic_update from mediagoblin import mg_globals as mgg - +from mediagoblin.db.util import atomic_update +from mediagoblin.db.models import MediaEntry +from mediagoblin.tools.pluginapi import hook_handle from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ _log = logging.getLogger(__name__) @@ -74,49 +82,89 @@ class FilenameBuilder(object): ext=self.ext) -class ProcessingState(object): - """ - The first and only argument to the "processor" of a media type - This could be thought of as a "request" to the processor - function. It has the main info for the request (media entry) - and a bunch of tools for the request on it. - It can get more fancy without impacting old media types. +class MediaProcessor(object): + """A particular processor for this media type. + + While the ProcessingManager handles all types of MediaProcessing + possible for a particular media type, a MediaProcessor can be + thought of as a *particular* processing action for a media type. + For example, you may have separate MediaProcessors for: + + - initial_processing: the intial processing of a media + - gen_thumb: generate a thumbnail + - resize: resize an image + - transcode: transcode a video + + ... etc. + + Some information on producing a new MediaProcessor for your media type: + + - You *must* supply a name attribute. This must be a class level + attribute, and a string. This will be used to determine the + subcommand of your process + - It's recommended that you supply a class level description + attribute. + - Supply a media_is_eligible classmethod. This will be used to + determine whether or not a media entry is eligible to use this + processor type. See the method documentation for details. + - To give "./bin/gmg reprocess run" abilities to this media type, + supply both gnerate_parser and parser_to_request classmethods. + - The process method will be what actually processes your media. """ - def __init__(self, entry): + # You MUST override this in the child MediaProcessor! + name = None + + # Optional, but will be used in various places to describe the + # action this MediaProcessor provides + description = None + + def __init__(self, manager, entry): + self.manager = manager self.entry = entry + self.entry_orig_state = entry.state + + # Should be initialized at time of processing, at least self.workbench = None - self.queued_filename = None - def set_workbench(self, wb): - self.workbench = wb + def __enter__(self): + self.workbench = mgg.workbench_manager.create() + return self + + def __exit__(self, *args): + self.workbench.destroy() + self.workbench = None - def get_queued_filename(self): + # @with_workbench + def process(self, **kwargs): """ - Get the a filename for the original, on local storage + Actually process this media entry. """ - if self.queued_filename is not None: - return self.queued_filename - queued_filepath = self.entry.queued_media_file - queued_filename = self.workbench.localized_file( - mgg.queue_store, queued_filepath, - 'source') - self.queued_filename = queued_filename - return queued_filename - - def copy_original(self, target_name, keyname=u"original"): - self.store_public(keyname, self.get_queued_filename(), target_name) - - def store_public(self, keyname, local_file, target_name=None): - if target_name is None: - target_name = os.path.basename(local_file) - target_filepath = create_pub_filepath(self.entry, target_name) - if keyname in self.entry.media_files: - _log.warn("store_public: keyname %r already used for file %r, " - "replacing with %r", keyname, - self.entry.media_files[keyname], target_filepath) - mgg.public_store.copy_local_to_storage(local_file, target_filepath) - self.entry.media_files[keyname] = target_filepath + raise NotImplementedError + + @classmethod + def media_is_eligible(cls, entry=None, state=None): + raise NotImplementedError + + ############################### + # Command line interface things + ############################### + + @classmethod + def generate_parser(cls): + raise NotImplementedError + + @classmethod + def args_to_request(cls, args): + raise NotImplementedError + + ########################################## + # THE FUTURE: web interface things here :) + ########################################## + + ##################### + # Some common "steps" + ##################### def delete_queue_file(self): # Remove queued media file from storage and database. @@ -124,9 +172,130 @@ class ProcessingState(object): # be removed too, but fail if the directory is not empty to be on # the super-safe side. queued_filepath = self.entry.queued_media_file - mgg.queue_store.delete_file(queued_filepath) # rm file - mgg.queue_store.delete_dir(queued_filepath[:-1]) # rm dir - self.entry.queued_media_file = [] + if queued_filepath: + mgg.queue_store.delete_file(queued_filepath) # rm file + mgg.queue_store.delete_dir(queued_filepath[:-1]) # rm dir + self.entry.queued_media_file = [] + + +class ProcessingKeyError(Exception): pass +class ProcessorDoesNotExist(ProcessingKeyError): pass +class ProcessorNotEligible(ProcessingKeyError): pass +class ProcessingManagerDoesNotExist(ProcessingKeyError): pass + + + +class ProcessingManager(object): + """Manages all the processing actions available for a media type + + Specific processing actions, MediaProcessor subclasses, are added + to the ProcessingManager. + """ + def __init__(self): + # Dict of all MediaProcessors of this media type + if OrderedDict is not None: + self.processors = OrderedDict() + else: + self.processors = {} + + def add_processor(self, processor): + """ + Add a processor class to this media type + """ + name = processor.name + if name is None: + raise AttributeError("Processor class's .name attribute not set") + + self.processors[name] = processor + + def list_eligible_processors(self, entry): + """ + List all processors that this media entry is eligible to be processed + for. + """ + return [ + processor + for processor in self.processors.values() + if processor.media_is_eligible(entry=entry)] + + def list_all_processors_by_state(self, state): + """ + List all processors that this media state is eligible to be processed + for. + """ + return [ + processor + for processor in self.processors.values() + if processor.media_is_eligible(state=state)] + + + def list_all_processors(self): + return self.processors.values() + + def gen_process_request_via_cli(self, subparser): + # Got to figure out what actually goes here before I can write this properly + pass + + def get_processor(self, key, entry=None): + """ + Get the processor with this key. + + If entry supplied, make sure this entry is actually compatible; + otherwise raise error. + """ + try: + processor = self.processors[key] + except KeyError: + raise ProcessorDoesNotExist( + "'%s' processor does not exist for this media type" % key) + + if entry and not processor.media_is_eligible(entry): + raise ProcessorNotEligible( + "This entry is not eligible for processor with name '%s'" % key) + + return processor + + +def request_from_args(args, which_args): + """ + Generate a request from the values of some argparse parsed args + """ + request = {} + for arg in which_args: + request[arg] = getattr(args, arg) + + return request + + +class MediaEntryNotFound(Exception): pass + + +def get_processing_manager_for_type(media_type): + """ + Get the appropriate media manager for this type + """ + manager_class = hook_handle(('reprocess_manager', media_type)) + if not manager_class: + raise ProcessingManagerDoesNotExist( + "A processing manager does not exist for {0}".format(media_type)) + manager = manager_class() + + return manager + + +def get_entry_and_processing_manager(media_id): + """ + Get a MediaEntry, its media type, and its manager all in one go. + + Returns a tuple of: `(entry, media_type, media_manager)` + """ + entry = MediaEntry.query.filter_by(id=media_id).first() + if entry is None: + raise MediaEntryNotFound("Can't find media with id '%s'" % media_id) + + manager = get_processing_manager_for_type(entry.media_type) + + return entry, manager def mark_entry_failed(entry_id, exc): @@ -165,13 +334,72 @@ def mark_entry_failed(entry_id, exc): u'fail_metadata': {}}) +def get_process_filename(entry, workbench, acceptable_files): + """ + Try and get the queued file if available, otherwise return the first file + in the acceptable_files that we have. + + If no acceptable_files, raise ProcessFileNotFound + """ + if entry.queued_media_file: + filepath = entry.queued_media_file + storage = mgg.queue_store + else: + for keyname in acceptable_files: + if entry.media_files.get(keyname): + filepath = entry.media_files[keyname] + storage = mgg.public_store + break + + if not filepath: + raise ProcessFileNotFound() + + filename = workbench.localized_file( + storage, filepath, + 'source') + + if not os.path.exists(filename): + raise ProcessFileNotFound() + + return filename + + +def store_public(entry, keyname, local_file, target_name=None, + delete_if_exists=True): + if target_name is None: + target_name = os.path.basename(local_file) + target_filepath = create_pub_filepath(entry, target_name) + + if keyname in entry.media_files: + _log.warn("store_public: keyname %r already used for file %r, " + "replacing with %r", keyname, + entry.media_files[keyname], target_filepath) + if delete_if_exists: + mgg.public_store.delete_file(entry.media_files[keyname]) + + try: + mgg.public_store.copy_local_to_storage(local_file, target_filepath) + except: + raise PublicStoreFail(keyname=keyname) + + # raise an error if the file failed to copy + if not mgg.public_store.file_exists(target_filepath): + raise PublicStoreFail(keyname=keyname) + + entry.media_files[keyname] = target_filepath + + +def copy_original(entry, orig_filename, target_name, keyname=u"original"): + store_public(entry, keyname, orig_filename, target_name) + + class BaseProcessingFail(Exception): """ Base exception that all other processing failure messages should subclass from. You shouldn't call this itself; instead you should subclass it - and provid the exception_path and general_message applicable to + and provide the exception_path and general_message applicable to this error. """ general_message = u'' @@ -184,10 +412,24 @@ class BaseProcessingFail(Exception): def __init__(self, **metadata): self.metadata = metadata or {} - class BadMediaFail(BaseProcessingFail): """ Error that should be raised when an inappropriate file was given for the media type specified. """ general_message = _(u'Invalid file given for media type.') + + +class PublicStoreFail(BaseProcessingFail): + """ + Error that should be raised when copying to public store fails + """ + general_message = _('Copying to public storage failed.') + + +class ProcessFileNotFound(BaseProcessingFail): + """ + Error that should be raised when an acceptable file for processing + is not found. + """ + general_message = _(u'An acceptable processing file was not found') diff --git a/mediagoblin/processing/task.py b/mediagoblin/processing/task.py index 9af192ed..7f683485 100644 --- a/mediagoblin/processing/task.py +++ b/mediagoblin/processing/task.py @@ -18,19 +18,20 @@ import logging import urllib import urllib2 -from celery import registry, task +import celery +from celery.registry import tasks from mediagoblin import mg_globals as mgg -from mediagoblin.db.models import MediaEntry -from . import mark_entry_failed, BaseProcessingFail, ProcessingState +from . import mark_entry_failed, BaseProcessingFail from mediagoblin.tools.processing import json_processing_callback +from mediagoblin.processing import get_entry_and_processing_manager _log = logging.getLogger(__name__) logging.basicConfig() _log.setLevel(logging.DEBUG) -@task.task(default_retry_delay=2 * 60) +@celery.task(default_retry_delay=2 * 60) def handle_push_urls(feed_url): """Subtask, notifying the PuSH servers of new content @@ -60,36 +61,51 @@ def handle_push_urls(feed_url): 'Giving up.'.format(feed_url)) return False + ################################ # Media processing initial steps ################################ - -class ProcessMedia(task.Task): +class ProcessMedia(celery.Task): """ Pass this entry off for processing. """ - def run(self, media_id, feed_url): + def run(self, media_id, feed_url, reprocess_action, reprocess_info=None): """ Pass the media entry off to the appropriate processing function (for now just process_image...) :param feed_url: The feed URL that the PuSH server needs to be updated for. + :param reprocess: A dict containing all of the necessary reprocessing + info for the media_type. """ - entry = MediaEntry.query.get(media_id) + reprocess_info = reprocess_info or {} + entry, manager = get_entry_and_processing_manager(media_id) # Try to process, and handle expected errors. try: - entry.state = u'processing' - entry.save() - - _log.debug('Processing {0}'.format(entry)) - - proc_state = ProcessingState(entry) - with mgg.workbench_manager.create() as workbench: - proc_state.set_workbench(workbench) - # run the processing code - entry.media_manager.processor(proc_state) + processor_class = manager.get_processor(reprocess_action, entry) + + with processor_class(manager, entry) as processor: + # Initial state change has to be here because + # the entry.state gets recorded on processor_class init + entry.state = u'processing' + entry.save() + + _log.debug('Processing {0}'.format(entry)) + + try: + processor.process(**reprocess_info) + except Exception as exc: + if processor.entry_orig_state == 'processed': + _log.error( + 'Entry {0} failed to process due to the following' + ' error: {1}'.format(entry.id, exc)) + _log.info( + 'Setting entry.state back to "processed"') + pass + else: + raise # We set the state to processed and save the entry here so there's # no need to save at the end of the processing stage, probably ;) @@ -140,6 +156,4 @@ class ProcessMedia(task.Task): entry = mgg.database.MediaEntry.query.filter_by(id=entry_id).first() json_processing_callback(entry) -# Register the task -process_media = registry.tasks[ProcessMedia.name] - +tasks.register(ProcessMedia) diff --git a/mediagoblin/routing.py b/mediagoblin/routing.py index a650f22f..1393f01c 100644 --- a/mediagoblin/routing.py +++ b/mediagoblin/routing.py @@ -18,7 +18,7 @@ import logging from mediagoblin.tools.routing import add_route, mount, url_map from mediagoblin.tools.pluginapi import PluginManager -from mediagoblin.admin.routing import admin_routes +from mediagoblin.moderation.routing import moderation_routes from mediagoblin.auth.routing import auth_routes @@ -27,15 +27,20 @@ _log = logging.getLogger(__name__) def get_url_map(): add_route('index', '/', 'mediagoblin.views:root_view') + add_route('terms_of_service','/terms_of_service', + 'mediagoblin.views:terms_of_service') mount('/auth', auth_routes) - mount('/a', admin_routes) + mount('/mod', moderation_routes) import mediagoblin.submit.routing import mediagoblin.user_pages.routing import mediagoblin.edit.routing import mediagoblin.webfinger.routing import mediagoblin.listings.routing + import mediagoblin.notifications.routing + import mediagoblin.oauth.routing + for route in PluginManager().get_routes(): add_route(*route) diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css index 0cb36753..7b422167 100644 --- a/mediagoblin/static/css/base.css +++ b/mediagoblin/static/css/base.css @@ -129,6 +129,7 @@ header { .header_dropdown { margin-bottom: 20px; + padding: 0px 10px 0px 10px; } .header_dropdown li { @@ -155,6 +156,10 @@ a.logo { margin: 6px 8px 6px 0; } +.fine_print { + font-size: 0.8em; +} + .mediagoblin_content { width: 100%; padding-bottom: 74px; @@ -219,6 +224,7 @@ footer { color: #283F35; } + .button_form { min-width: 99px; margin: 10px 0px 10px 15px; @@ -287,6 +293,48 @@ text-align: center; max-width: 460px; } +.blog_form_box_xl { + background-color: #222; + border-top: 6px solid #D49086; + padding: 3% 5%; + display: block; + float: none; + width: 90%; + max-width: 800px; + min-height: 500px; + margin-left: auto; + margin-right: auto; +} + +.b_listing_title { + height: 30px; + width: 100%; + padding: 0px; + background-color: #86D4B1; + text-transform:capitalize; + text-decoration: none; + #border-radius: 4px; +} + +.b_listing_title > a { + text-decoration: none; +} + +.b_list_owner { + height: 100px; + width: 100%; + padding: 0em; + margin-right: auto; + background-color: #DDA0DD; + #border-radius: 4px; + text-transform: capitalize; +} + +.b_list_des { + text-align:justify; +} + + .edit_box { border-top: 6px dashed #D49086 } @@ -295,6 +343,10 @@ text-align: center; width: 100%; } +.blog_form_field_input input, .blog_form_field_input textarea { + width: 100%; +} + .form_field_input { margin-bottom: 10px; } @@ -333,6 +385,10 @@ text-align: center; width: 20px; } +.boolean { + margin-bottom: 8px; + } + textarea#description, textarea#bio { resize: vertical; height: 100px; @@ -346,44 +402,50 @@ textarea#description, textarea#bio { /* comments */ -.comment_wrapper { +.comment_wrapper, .report_wrapper { margin-top: 20px; margin-bottom: 20px; } -.comment_wrapper p { +.comment_wrapper p, .report_wrapper p { margin-bottom: 2px; } -.comment_author { +.comment_author, .report_author { padding-top: 4px; font-size: 0.9em; } -a.comment_authorlink { +a.comment_authorlink, a.report_authorlink { text-decoration: none; padding-right: 5px; font-weight: bold; padding-left: 2px; } -a.comment_authorlink:hover { +a.comment_authorlink:hover, a.report_authorlink:hover { text-decoration: underline; } -a.comment_whenlink { +a.comment_whenlink, a.report_whenlink { text-decoration: none; } -a.comment_whenlink:hover { +a.comment_whenlink:hover, a.report_whenlink:hover { text-decoration: underline; } -.comment_content { +.comment_content, .report_content { margin-left: 8px; margin-top: 8px; } +.comment_active { + box-shadow: 0px 0px 15px 15px #378566; + background: #378566; + color: #f7f7f7; +} + textarea#comment_content { resize: vertical; width: 100%; @@ -397,6 +459,13 @@ textarea#comment_content { padding-right: 6px; } + +a.report_authorlink, a.report_whenlink { + color: #D486B1; +} + +ul#action_to_resolve {list-style:none; margin-left:10px;} + /* media galleries */ .media_thumbnail { @@ -433,9 +502,12 @@ a.thumb_entry_title { padding: 8px; } -.media_thumbnail img { - max-height: 135px; -} +/* For now, this is commented out since our thumbnails are actually 180px high. + * + * .media_thumbnail img { + * max-height: 135px; + * } + */ .thumb_entry_last { margin-right: 0px; @@ -481,6 +553,38 @@ img.media_icon { vertical-align: sub; } +/* EXIF information */ + +#exif_content h3 { + border-bottom: 1px solid #333; +} + +#exif_camera_information { + margin-bottom: 20px; +} + +#exif_additional_info { + display: none; +} + +#exif_additional_info table { + font-size: 11px; + margin-top: 10px; +} + +#exif_additional_info td { + vertical-align: top; + padding-bottom: 5px; +} + +#exif_content .col1 { + padding-right: 20px; +} + +#exif_additional_info table tr { + margin-bottom: 10px; +} + /* navigation */ .navigation { @@ -562,6 +666,38 @@ table.media_panel th { text-align: left; } +/* moderator panels */ + +table.admin_panel { + width: 100% +} + +table.admin_side_panel { + width: 60% +} + +table.admin_panel th, table.admin_side_panel th { + font-weight: bold; + padding-bottom: 4px; + text-align: left; + color: #fff; +} + +table td.user_with_privilege { + font-weight: bold; + color: #86D4B1; +} + +table td.user_without_privilege { + font-weight: bold; + color: #D486B1; +} + +.return_to_panel { + text-align:right; + float: right; + font-size:1.2em +} /* Delete panel */ @@ -570,6 +706,27 @@ table.media_panel th { margin-left: 10px; } +/* code of conduct */ + +#code_of_conduct_list { + margin-left:25px; + margin-bottom: 10px; +} +#code_of_conduct_list li { + margin:5px 0 15px 25px; +} +#code_of_conduct_list strong{ + color:#fff; +} + +.nested_sublist { + margin: 5px 0 10px 25px; + font-size:80%; +} +.nested_sublist li { + margin-bottom: 10px; +} + /* ASCII art and code */ @font-face { @@ -685,3 +842,36 @@ pre { width: 46%; } } + +/* Exif display */ +#exif_content h3 { + border-bottom: 1px solid #333; +} +#exif_camera_information { + margin-bottom: 20px; +} + +#exif_additional_info { + display: none; +} +#exif_additional_info table { + font-size: 11px; + margin-top: 10px; +} +#exif_additional_info td { + vertical-align: top; + padding-bottom: 5px; +} +#exif_content .col1 { + padding-right: 20px; +} +#exif_additional_info table tr { + margin-bottom: 10px; +} + +p.verifier { + text-align:center; + font-size:50px; + none repeat scroll 0% 0% rgb(221, 221, 221); + padding: 1em 0px; +} diff --git a/mediagoblin/static/css/pdf_viewer.css b/mediagoblin/static/css/pdf_viewer.css deleted file mode 100644 index c04c8981..00000000 --- a/mediagoblin/static/css/pdf_viewer.css +++ /dev/null @@ -1,1448 +0,0 @@ -/* Copyright 2012 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -* { - padding: 0; - margin: 0; -} - -html { - height: 100%; -} - -body { - height: 100%; - background-color: #404040; - background-image: url(../extlib/pdf.js/web/images/texture.png); -} - -body, -input, -button, -select { - font: message-box; -} - -.hidden { - display: none; -} -[hidden] { - display: none !important; -} - -#viewerContainer:-webkit-full-screen { - top: 0px; - border-top: 2px solid transparent; - background-color: #404040; - background-image: url(../extlib/pdf.js/web/images/texture.png); - width: 100%; - height: 100%; - overflow: hidden; - cursor: none; -} - -#viewerContainer:-moz-full-screen { - top: 0px; - border-top: 2px solid transparent; - background-color: #404040; - background-image: url(../extlib/pdf.js/web/images/texture.png); - width: 100%; - height: 100%; - overflow: hidden; - cursor: none; -} - -#viewerContainer:fullscreen { - top: 0px; - border-top: 2px solid transparent; - background-color: #404040; - background-image: url(../extlib/pdf.js/web/images/texture.png); - width: 100%; - height: 100%; - overflow: hidden; - cursor: none; -} - - -:-webkit-full-screen .page { - margin-bottom: 100%; -} - -:-moz-full-screen .page { - margin-bottom: 100%; -} - -:fullscreen .page { - margin-bottom: 100%; -} - -#viewerContainer.presentationControls { - cursor: default; -} - -/* outer/inner center provides horizontal center */ -html[dir='ltr'] .outerCenter { - float: right; - position: relative; - right: 50%; -} -html[dir='rtl'] .outerCenter { - float: left; - position: relative; - left: 50%; -} -html[dir='ltr'] .innerCenter { - float: right; - position: relative; - right: -50%; -} -html[dir='rtl'] .innerCenter { - float: left; - position: relative; - left: -50%; -} - -#outerContainer { - width: 100%; - height: 100%; -} - -#sidebarContainer { - left: 0; - right: 0; - height: 200px; - visibility: hidden; - -webkit-transition-duration: 200ms; - -webkit-transition-timing-function: ease; - -moz-transition-duration: 200ms; - -moz-transition-timing-function: ease; - -ms-transition-duration: 200ms; - -ms-transition-timing-function: ease; - -o-transition-duration: 200ms; - -o-transition-timing-function: ease; - transition-duration: 200ms; - transition-timing-function: ease; - -} -html[dir='ltr'] #sidebarContainer { - -webkit-transition-property: top; - -moz-transition-property: top; - -ms-transition-property: top; - -o-transition-property: top; - transition-property: top; - top: -200px; -} -html[dir='rtl'] #sidebarContainer { - -webkit-transition-property: top; - -ms-transition-property: top; - -o-transition-property: top; - transition-property: top; - top: -200px; -} - -#outerContainer.sidebarMoving > #sidebarContainer, -#outerContainer.sidebarOpen > #sidebarContainer { - visibility: visible; -} -html[dir='ltr'] #outerContainer.sidebarOpen > #sidebarContainer { - left: 0px; -} -html[dir='rtl'] #outerContainer.sidebarOpen > #sidebarContainer { - right: 0px; -} - -#mainContainer { - top: 0; - right: 0; - bottom: 0; - left: 0; - min-width: 320px; - -webkit-transition-duration: 200ms; - -webkit-transition-timing-function: ease; - -moz-transition-duration: 200ms; - -moz-transition-timing-function: ease; - -ms-transition-duration: 200ms; - -ms-transition-timing-function: ease; - -o-transition-duration: 200ms; - -o-transition-timing-function: ease; - transition-duration: 200ms; - transition-timing-function: ease; -} -html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer { - -webkit-transition-property: left; - -moz-transition-property: left; - -ms-transition-property: left; - -o-transition-property: left; - transition-property: left; - left: 200px; -} -html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer { - -webkit-transition-property: right; - -moz-transition-property: right; - -ms-transition-property: right; - -o-transition-property: right; - transition-property: right; - right: 200px; -} - -#sidebarContent { - top: 32px; - bottom: 0; - overflow: auto; - height: 200px; - - background-color: hsla(0,0%,0%,.1); - box-shadow: inset -1px 0 0 hsla(0,0%,0%,.25); -} -html[dir='ltr'] #sidebarContent { - left: 0; -} -html[dir='rtl'] #sidebarContent { - right: 0; -} - -#viewerContainer { - overflow: auto; - box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05); - top: 32px; - right: 0; - bottom: 0; - left: 0; - height: 480px; - width: 640px; -} - -.toolbar { - left: 0; - right: 0; - height: 32px; - z-index: 9999; - cursor: default; -} - -#toolbarContainer { - width: 100%; -} - -#toolbarSidebar { - width: 200px; - height: 32px; - background-image: url(../extlib/pdf.js/web/images/texture.png), - -webkit-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); - background-image: url(../extlib/pdf.js/web/images/texture.png), - -moz-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); - background-image: url(../extlib/pdf.js/web/images/texture.png), - -ms-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); - background-image: url(../extlib/pdf.js/web/images/texture.png), - -o-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); - background-image: url(../extlib/pdf.js/web/images/texture.png), - linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); - box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.25), - - inset 0 -1px 0 hsla(0,0%,100%,.05), - 0 1px 0 hsla(0,0%,0%,.15), - 0 0 1px hsla(0,0%,0%,.1); -} - -#toolbarViewer, .findbar { - position: relative; - height: 32px; - background-color: #474747; /* IE9 */ - background-image: url(../extlib/pdf.js/web/images/texture.png), - -webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); - background-image: url(../extlib/pdf.js/web/images/texture.png), - -moz-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); - background-image: url(../extlib/pdf.js/web/images/texture.png), - -ms-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); - background-image: url(../extlib/pdf.js/web/images/texture.png), - -o-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); - background-image: url(../extlib/pdf.js/web/images/texture.png), - linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); - box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08), - inset 0 1px 1px hsla(0,0%,0%,.15), - inset 0 -1px 0 hsla(0,0%,100%,.05), - 0 1px 0 hsla(0,0%,0%,.15), - 0 1px 1px hsla(0,0%,0%,.1); -} - -.findbar { - top: 64px; - z-index: 10000; - height: 32px; - - min-width: 16px; - padding: 0px 6px 0px 6px; - margin: 4px 2px 4px 2px; - color: hsl(0,0%,85%); - font-size: 12px; - line-height: 14px; - text-align: left; - cursor: default; -} - -html[dir='ltr'] .findbar { - left: 68px; -} - -html[dir='rtl'] .findbar { - right: 68px; -} - -.findbar label { - -webkit-user-select: none; - -moz-user-select: none; -} - -#findInput[data-status="pending"] { - background-image: url(../extlib/pdf.js/web/images/loading-small.png); - background-repeat: no-repeat; - background-position: right; -} - -.doorHanger { - border: 1px solid hsla(0,0%,0%,.5); - border-radius: 2px; - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); -} -.doorHanger:after, .doorHanger:before { - bottom: 100%; - border: solid transparent; - content: " "; - height: 0; - width: 0; - pointer-events: none; -} -.doorHanger:after { - border-bottom-color: hsla(0,0%,32%,.99); - border-width: 8px; -} -.doorHanger:before { - border-bottom-color: hsla(0,0%,0%,.5); - border-width: 9px; -} - -html[dir='ltr'] .doorHanger:after { - left: 13px; - margin-left: -8px; -} - -html[dir='ltr'] .doorHanger:before { - left: 13px; - margin-left: -9px; -} - -html[dir='rtl'] .doorHanger:after { - right: 13px; - margin-right: -8px; -} - -html[dir='rtl'] .doorHanger:before { - right: 13px; - margin-right: -9px; -} - -#findMsg { - font-style: italic; - color: #A6B7D0; -} - -.notFound { - background-color: rgb(255, 137, 153); -} - -html[dir='ltr'] #toolbarViewerLeft { - margin-left: -1px; -} -html[dir='rtl'] #toolbarViewerRight { - margin-left: -1px; -} - - -html[dir='ltr'] #toolbarViewerLeft, -html[dir='rtl'] #toolbarViewerRight { - position: absolute; - top: 0; - left: 0; -} -html[dir='ltr'] #toolbarViewerRight, -html[dir='rtl'] #toolbarViewerLeft { - position: absolute; - top: 0; - right: 0; -} -html[dir='ltr'] #toolbarViewerLeft > *, -html[dir='ltr'] #toolbarViewerMiddle > *, -html[dir='ltr'] #toolbarViewerRight > *, -html[dir='ltr'] .findbar > * { - float: left; -} -html[dir='rtl'] #toolbarViewerLeft > *, -html[dir='rtl'] #toolbarViewerMiddle > *, -html[dir='rtl'] #toolbarViewerRight > *, -html[dir='rtl'] .findbar > * { - float: right; -} - -html[dir='ltr'] .splitToolbarButton { - margin: 3px 2px 4px 0; - display: inline-block; -} -html[dir='rtl'] .splitToolbarButton { - margin: 3px 0 4px 2px; - display: inline-block; -} -html[dir='ltr'] .splitToolbarButton > .toolbarButton { - border-radius: 0; - float: left; -} -html[dir='rtl'] .splitToolbarButton > .toolbarButton { - border-radius: 0; - float: right; -} - -.toolbarButton { - border: 0 none; - background-color: rgba(0, 0, 0, 0); - width: 32px; - height: 25px; -} - -.toolbarButton > span { - display: inline-block; - width: 0; - height: 0; - overflow: hidden; -} - -.toolbarButton[disabled] { - opacity: .5; -} - -.toolbarButton.group { - margin-right: 0; -} - -.splitToolbarButton.toggled .toolbarButton { - margin: 0; -} - -.splitToolbarButton:hover > .toolbarButton, -.splitToolbarButton:focus > .toolbarButton, -.splitToolbarButton.toggled > .toolbarButton, -.toolbarButton.textButton { - background-color: hsla(0,0%,0%,.12); - background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-clip: padding-box; - border: 1px solid hsla(0,0%,0%,.35); - border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); - box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, - 0 0 1px hsla(0,0%,100%,.15) inset, - 0 1px 0 hsla(0,0%,100%,.05); - -webkit-transition-property: background-color, border-color, box-shadow; - -webkit-transition-duration: 150ms; - -webkit-transition-timing-function: ease; - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 150ms; - -moz-transition-timing-function: ease; - -ms-transition-property: background-color, border-color, box-shadow; - -ms-transition-duration: 150ms; - -ms-transition-timing-function: ease; - -o-transition-property: background-color, border-color, box-shadow; - -o-transition-duration: 150ms; - -o-transition-timing-function: ease; - transition-property: background-color, border-color, box-shadow; - transition-duration: 150ms; - transition-timing-function: ease; - -} -.splitToolbarButton > .toolbarButton:hover, -.splitToolbarButton > .toolbarButton:focus, -.dropdownToolbarButton:hover, -.toolbarButton.textButton:hover, -.toolbarButton.textButton:focus { - background-color: hsla(0,0%,0%,.2); - box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, - 0 0 1px hsla(0,0%,100%,.15) inset, - 0 0 1px hsla(0,0%,0%,.05); - z-index: 199; -} -html[dir='ltr'] .splitToolbarButton > .toolbarButton:first-child, -html[dir='rtl'] .splitToolbarButton > .toolbarButton:last-child { - position: relative; - margin: 0; - margin-right: -1px; - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; - border-right-color: transparent; -} -html[dir='ltr'] .splitToolbarButton > .toolbarButton:last-child, -html[dir='rtl'] .splitToolbarButton > .toolbarButton:first-child { - position: relative; - margin: 0; - margin-left: -1px; - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; - border-left-color: transparent; -} -.splitToolbarButtonSeparator { - padding: 8px 0; - width: 1px; - background-color: hsla(0,0%,00%,.5); - z-index: 99; - box-shadow: 0 0 0 1px hsla(0,0%,100%,.08); - display: inline-block; - margin: 5px 0; -} -html[dir='ltr'] .splitToolbarButtonSeparator { - float: left; -} -html[dir='rtl'] .splitToolbarButtonSeparator { - float: right; -} -.splitToolbarButton:hover > .splitToolbarButtonSeparator, -.splitToolbarButton.toggled > .splitToolbarButtonSeparator { - padding: 12px 0; - margin: 1px 0; - box-shadow: 0 0 0 1px hsla(0,0%,100%,.03); - -webkit-transition-property: padding; - -webkit-transition-duration: 10ms; - -webkit-transition-timing-function: ease; - -moz-transition-property: padding; - -moz-transition-duration: 10ms; - -moz-transition-timing-function: ease; - -ms-transition-property: padding; - -ms-transition-duration: 10ms; - -ms-transition-timing-function: ease; - -o-transition-property: padding; - -o-transition-duration: 10ms; - -o-transition-timing-function: ease; - transition-property: padding; - transition-duration: 10ms; - transition-timing-function: ease; -} - -.toolbarButton, -.dropdownToolbarButton { - min-width: 16px; - padding: 2px 6px 0; - border: 1px solid transparent; - border-radius: 2px; - color: hsl(0,0%,95%); - font-size: 12px; - line-height: 14px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - /* Opera does not support user-select, use <... unselectable="on"> instead */ - cursor: default; - -webkit-transition-property: background-color, border-color, box-shadow; - -webkit-transition-duration: 150ms; - -webkit-transition-timing-function: ease; - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 150ms; - -moz-transition-timing-function: ease; - -ms-transition-property: background-color, border-color, box-shadow; - -ms-transition-duration: 150ms; - -ms-transition-timing-function: ease; - -o-transition-property: background-color, border-color, box-shadow; - -o-transition-duration: 150ms; - -o-transition-timing-function: ease; - transition-property: background-color, border-color, box-shadow; - transition-duration: 150ms; - transition-timing-function: ease; -} - -html[dir='ltr'] .toolbarButton, -html[dir='ltr'] .dropdownToolbarButton { - margin: 3px 2px 4px 0; -} -html[dir='rtl'] .toolbarButton, -html[dir='rtl'] .dropdownToolbarButton { - margin: 3px 0 4px 2px; -} - -.toolbarButton:hover, -.toolbarButton:focus, -.dropdownToolbarButton { - background-color: hsla(0,0%,0%,.12); - background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-clip: padding-box; - border: 1px solid hsla(0,0%,0%,.35); - border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); - box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, - 0 0 1px hsla(0,0%,100%,.15) inset, - 0 1px 0 hsla(0,0%,100%,.05); -} - -.toolbarButton:hover:active, -.dropdownToolbarButton:hover:active { - background-color: hsla(0,0%,0%,.2); - background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45); - box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, - 0 0 1px hsla(0,0%,0%,.2) inset, - 0 1px 0 hsla(0,0%,100%,.05); - -webkit-transition-property: background-color, border-color, box-shadow; - -webkit-transition-duration: 10ms; - -webkit-transition-timing-function: linear; - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 10ms; - -moz-transition-timing-function: linear; - -ms-transition-property: background-color, border-color, box-shadow; - -ms-transition-duration: 10ms; - -ms-transition-timing-function: linear; - -o-transition-property: background-color, border-color, box-shadow; - -o-transition-duration: 10ms; - -o-transition-timing-function: linear; - transition-property: background-color, border-color, box-shadow; - transition-duration: 10ms; - transition-timing-function: linear; -} - -.toolbarButton.toggled, -.splitToolbarButton.toggled > .toolbarButton.toggled { - background-color: hsla(0,0%,0%,.3); - background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.45) hsla(0,0%,0%,.5); - box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, - 0 0 1px hsla(0,0%,0%,.2) inset, - 0 1px 0 hsla(0,0%,100%,.05); - -webkit-transition-property: background-color, border-color, box-shadow; - -webkit-transition-duration: 10ms; - -webkit-transition-timing-function: linear; - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 10ms; - -moz-transition-timing-function: linear; - -ms-transition-property: background-color, border-color, box-shadow; - -ms-transition-duration: 10ms; - -ms-transition-timing-function: linear; - -o-transition-property: background-color, border-color, box-shadow; - -o-transition-duration: 10ms; - -o-transition-timing-function: linear; - transition-property: background-color, border-color, box-shadow; - transition-duration: 10ms; - transition-timing-function: linear; -} - -.toolbarButton.toggled:hover:active, -.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active { - background-color: hsla(0,0%,0%,.4); - border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.5) hsla(0,0%,0%,.55); - box-shadow: 0 1px 1px hsla(0,0%,0%,.2) inset, - 0 0 1px hsla(0,0%,0%,.3) inset, - 0 1px 0 hsla(0,0%,100%,.05); -} - -.dropdownToolbarButton { - width: 120px; - max-width: 120px; - padding: 3px 2px 2px; - overflow: hidden; - background: url(../extlib/pdf.js/web/images/toolbarButton-menuArrows.png) no-repeat; -} -html[dir='ltr'] .dropdownToolbarButton { - background-position: 95%; -} -html[dir='rtl'] .dropdownToolbarButton { - background-position: 5%; -} - -.dropdownToolbarButton > select { - -webkit-appearance: none; - -moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */ - min-width: 140px; - font-size: 12px; - color: hsl(0,0%,95%); - margin: 0; - padding: 0; - border: none; - background: rgba(0,0,0,0); /* Opera does not support 'transparent' <select> background */ -} - -.dropdownToolbarButton > select > option { - background: hsl(0,0%,24%); -} - -#customScaleOption { - display: none; -} - -#pageWidthOption { - border-bottom: 1px rgba(255, 255, 255, .5) solid; -} - -html[dir='ltr'] .splitToolbarButton:first-child, -html[dir='ltr'] .toolbarButton:first-child, -html[dir='rtl'] .splitToolbarButton:last-child, -html[dir='rtl'] .toolbarButton:last-child { - margin-left: 4px; -} -html[dir='ltr'] .splitToolbarButton:last-child, -html[dir='ltr'] .toolbarButton:last-child, -html[dir='rtl'] .splitToolbarButton:first-child, -html[dir='rtl'] .toolbarButton:first-child { - margin-right: 4px; -} - -.toolbarButtonSpacer { - width: 30px; - display: inline-block; - height: 1px; -} - -.toolbarButtonFlexibleSpacer { - -webkit-box-flex: 1; - -moz-box-flex: 1; - min-width: 30px; -} - -.toolbarButton#sidebarToggle::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-sidebarToggle.png); -} - -html[dir='ltr'] #findPrevious { - margin-left: 3px; -} -html[dir='ltr'] #findNext { - margin-right: 3px; -} - -html[dir='rtl'] #findPrevious { - margin-right: 3px; -} -html[dir='rtl'] #findNext { - margin-left: 3px; -} - -html[dir='ltr'] .toolbarButton.findPrevious::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/findbarButton-previous.png); -} - -html[dir='rtl'] .toolbarButton.findPrevious::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/findbarButton-previous-rtl.png); -} - -html[dir='ltr'] .toolbarButton.findNext::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/findbarButton-next.png); -} - -html[dir='rtl'] .toolbarButton.findNext::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/findbarButton-next-rtl.png); -} - -html[dir='ltr'] .toolbarButton.pageUp::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-pageUp.png); -} - -html[dir='rtl'] .toolbarButton.pageUp::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-pageUp-rtl.png); -} - -html[dir='ltr'] .toolbarButton.pageDown::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-pageDown.png); -} - -html[dir='rtl'] .toolbarButton.pageDown::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-pageDown-rtl.png); -} - -.toolbarButton.zoomOut::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-zoomOut.png); -} - -.toolbarButton.zoomIn::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-zoomIn.png); -} - -.toolbarButton.fullscreen::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-fullscreen.png); -} - -.toolbarButton.print::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-print.png); -} - -.toolbarButton.openFile::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-openFile.png); -} - -.toolbarButton.download::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-download.png); -} - -.toolbarButton.bookmark { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - margin-top: 3px; - padding-top: 4px; -} - -#viewBookmark[href='#'] { - opacity: .5; - pointer-events: none; -} - -.toolbarButton.bookmark::before { - content: url(../extlib/pdf.js/web/images/toolbarButton-bookmark.png); -} - -#viewThumbnail.toolbarButton::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-viewThumbnail.png); -} - -#viewOutline.toolbarButton::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-viewOutline.png); -} - -#viewFind.toolbarButton::before { - display: inline-block; - content: url(../extlib/pdf.js/web/images/toolbarButton-search.png); -} - - -.toolbarField { - padding: 3px 6px; - margin: 4px 0 4px 0; - border: 1px solid transparent; - border-radius: 2px; - background-color: hsla(0,0%,100%,.09); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-clip: padding-box; - border: 1px solid hsla(0,0%,0%,.35); - border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); - box-shadow: 0 1px 0 hsla(0,0%,0%,.05) inset, - 0 1px 0 hsla(0,0%,100%,.05); - color: hsl(0,0%,95%); - font-size: 12px; - line-height: 14px; - outline-style: none; - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 150ms; - -moz-transition-timing-function: ease; -} - -.toolbarField[type=checkbox] { - display: inline-block; - margin: 8px 0px; -} - -.toolbarField.pageNumber { - min-width: 16px; - text-align: right; - width: 40px; -} - -.toolbarField.pageNumber::-webkit-inner-spin-button, -.toolbarField.pageNumber::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; -} - -.toolbarField:hover { - background-color: hsla(0,0%,100%,.11); - border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.43) hsla(0,0%,0%,.45); -} - -.toolbarField:focus { - background-color: hsla(0,0%,100%,.15); - border-color: hsla(204,100%,65%,.8) hsla(204,100%,65%,.85) hsla(204,100%,65%,.9); -} - -.toolbarLabel { - min-width: 16px; - padding: 3px 6px 3px 2px; - margin: 4px 2px 4px 0; - border: 1px solid transparent; - border-radius: 2px; - color: hsl(0,0%,85%); - font-size: 12px; - line-height: 14px; - text-align: left; - -webkit-user-select: none; - -moz-user-select: none; - cursor: default; -} - -#thumbnailView { - top: 0; - bottom: 0; - padding: 10px 10px 0; - overflow: auto; -} - -.thumbnail { - float: left; -} - -.thumbnail:not([data-loaded]) { - border: 1px dashed rgba(255, 255, 255, 0.5); - margin-bottom: 10px; -} - -.thumbnailImage { - -moz-transition-duration: 150ms; - border: 1px solid transparent; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3); - opacity: 0.8; - z-index: 99; -} - -.thumbnailSelectionRing { - border-radius: 2px; - padding: 7px; - -moz-transition-duration: 150ms; -} - -a:focus > .thumbnail > .thumbnailSelectionRing > .thumbnailImage, -.thumbnail:hover > .thumbnailSelectionRing > .thumbnailImage { - opacity: .9; -} - -a:focus > .thumbnail > .thumbnailSelectionRing, -.thumbnail:hover > .thumbnailSelectionRing { - background-color: hsla(0,0%,100%,.15); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-clip: padding-box; - box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, - 0 0 1px hsla(0,0%,100%,.2) inset, - 0 0 1px hsla(0,0%,0%,.2); - color: hsla(0,0%,100%,.9); -} - -.thumbnail.selected > .thumbnailSelectionRing > .thumbnailImage { - box-shadow: 0 0 0 1px hsla(0,0%,0%,.5); - opacity: 1; -} - -.thumbnail.selected > .thumbnailSelectionRing { - background-color: hsla(0,0%,100%,.3); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-clip: padding-box; - box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, - 0 0 1px hsla(0,0%,100%,.1) inset, - 0 0 1px hsla(0,0%,0%,.2); - color: hsla(0,0%,100%,1); -} - -#outlineView { - width: 192px; - top: 0; - bottom: 0; - padding: 4px 4px 0; - overflow: auto; - -webkit-user-select: none; - -moz-user-select: none; -} - -html[dir='ltr'] .outlineItem > .outlineItems { - margin-left: 20px; -} - -html[dir='rtl'] .outlineItem > .outlineItems { - margin-right: 20px; -} - -.outlineItem > a { - text-decoration: none; - display: inline-block; - min-width: 95%; - height: auto; - margin-bottom: 1px; - border-radius: 2px; - color: hsla(0,0%,100%,.8); - font-size: 13px; - line-height: 15px; - -moz-user-select: none; - white-space: normal; -} - -html[dir='ltr'] .outlineItem > a { - padding: 2px 0 5px 10px; -} - -html[dir='rtl'] .outlineItem > a { - padding: 2px 10px 5px 0; -} - -.outlineItem > a:hover { - background-color: hsla(0,0%,100%,.02); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-clip: padding-box; - box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, - 0 0 1px hsla(0,0%,100%,.2) inset, - 0 0 1px hsla(0,0%,0%,.2); - color: hsla(0,0%,100%,.9); -} - -.outlineItem.selected { - background-color: hsla(0,0%,100%,.08); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-clip: padding-box; - box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, - 0 0 1px hsla(0,0%,100%,.1) inset, - 0 0 1px hsla(0,0%,0%,.2); - color: hsla(0,0%,100%,1); -} - -.noOutline, -.noResults { - font-size: 12px; - color: hsla(0,0%,100%,.8); - font-style: italic; - cursor: default; -} - -#findScrollView { - position: absolute; - top: 10px; - bottom: 10px; - left: 10px; - width: 280px; -} - -#sidebarControls { - position:absolute; - width: 180px; - height: 32px; - left: 15px; - bottom: 35px; -} - -canvas { - margin: auto; - display: block; -} - -.page { - direction: ltr; - width: 816px; - height: 1056px; - margin: 1px auto -8px auto; - position: relative; - overflow: visible; - border: 9px solid transparent; - background-clip: content-box; - border-image: url(../extlib/pdf.js/web/images/shadow.png) 9 9 repeat; - background-color: white; -} - -.page > a { - display: block; - position: absolute; -} - -.page > a:hover { - opacity: 0.2; - background: #ff0; - box-shadow: 0px 2px 10px #ff0; -} - -.loadingIcon { - position: absolute; - display: block; - left: 0; - top: 0; - right: 0; - bottom: 0; - background: url('../extlib/pdf.js/web/images/loading-icon.gif') center no-repeat; -} - -#loadingBox { - position: absolute; - top: 50%; - margin-top: -25px; - left: 0; - right: 0; - text-align: center; - color: #ddd; - font-size: 14px; -} - -#loadingBar { - display: inline-block; - clear: both; - margin: 0px; - margin-top: 5px; - line-height: 0; - border-radius: 2px; - width: 200px; - height: 25px; - - background-color: hsla(0,0%,0%,.3); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); - border: 1px solid #000; - box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, - 0 0 1px hsla(0,0%,0%,.2) inset, - 0 0 1px 1px rgba(255, 255, 255, 0.1); -} - -#loadingBar .progress { - display: inline-block; - float: left; - - background: #666; - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2b2b2), color-stop(100%,#898989)); - background: -webkit-linear-gradient(top, #b2b2b2 0%,#898989 100%); - background: -moz-linear-gradient(top, #b2b2b2 0%,#898989 100%); - background: -ms-linear-gradient(top, #b2b2b2 0%,#898989 100%); - background: -o-linear-gradient(top, #b2b2b2 0%,#898989 100%); - background: linear-gradient(top, #b2b2b2 0%,#898989 100%); - - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; - - width: 0%; - height: 100%; -} - -#loadingBar .progress.full { - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; -} - -#loadingBar .progress.indeterminate { - width: 100%; - height: 25px; - background-image: -moz-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040); - background-image: -webkit-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040); - background-image: -ms-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040); - background-image: -o-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040); - background-size: 75px 25px; - -moz-animation: progressIndeterminate 1s linear infinite; - -webkit-animation: progressIndeterminate 1s linear infinite; -} - -@-moz-keyframes progressIndeterminate { - from { background-position: 0px 0px; } - to { background-position: 75px 0px; } -} - -@-webkit-keyframes progressIndeterminate { - from { background-position: 0px 0px; } - to { background-position: 75px 0px; } -} - -.textLayer { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - color: #000; - font-family: sans-serif; - overflow: hidden; -} - -.textLayer > div { - color: transparent; - position: absolute; - line-height: 1; - white-space: pre; - cursor: text; -} - -.textLayer .highlight { - margin: -1px; - padding: 1px; - - background-color: rgba(180, 0, 170, 0.2); - border-radius: 4px; -} - -.textLayer .highlight.begin { - border-radius: 4px 0px 0px 4px; -} - -.textLayer .highlight.end { - border-radius: 0px 4px 4px 0px; -} - -.textLayer .highlight.middle { - border-radius: 0px; -} - -.textLayer .highlight.selected { - background-color: rgba(0, 100, 0, 0.2); -} - -/* TODO: file FF bug to support ::-moz-selection:window-inactive - so we can override the opaque grey background when the window is inactive; - see https://bugzilla.mozilla.org/show_bug.cgi?id=706209 */ -::selection { background:rgba(0,0,255,0.3); } -::-moz-selection { background:rgba(0,0,255,0.3); } - -.annotText > div { - z-index: 200; - position: absolute; - padding: 0.6em; - max-width: 20em; - background-color: #FFFF99; - box-shadow: 0px 2px 10px #333; - border-radius: 7px; -} - -.annotText > img { - position: absolute; - opacity: 0.6; -} - -.annotText > img:hover { - cursor: pointer; - opacity: 1; -} - -.annotText > div > h1 { - font-size: 1.2em; - border-bottom: 1px solid #000000; - margin: 0px; -} - -#errorWrapper { - background: none repeat scroll 0 0 #FF5555; - color: white; - left: 0; - position: absolute; - right: 0; - top: 32px; - z-index: 1000; - padding: 3px; - font-size: 0.8em; -} - -#errorMessageLeft { - float: left; -} - -#errorMessageRight { - float: right; -} - -#errorMoreInfo { - background-color: #FFFFFF; - color: black; - padding: 3px; - margin: 3px; - width: 98%; -} - -.clearBoth { - clear: both; -} - -.fileInput { - background: white; - color: black; - margin-top: 5px; -} - -#PDFBug { - background: none repeat scroll 0 0 white; - border: 1px solid #666666; - position: fixed; - top: 32px; - right: 0; - bottom: 0; - font-size: 10px; - padding: 0; - width: 300px; -} -#PDFBug .controls { - background:#EEEEEE; - border-bottom: 1px solid #666666; - padding: 3px; -} -#PDFBug .panels { - bottom: 0; - left: 0; - overflow: auto; - position: absolute; - right: 0; - top: 27px; -} -#PDFBug button.active { - font-weight: bold; -} -.debuggerShowText { - background: none repeat scroll 0 0 yellow; - color: blue; - opacity: 0.3; -} -.debuggerHideText:hover { - background: none repeat scroll 0 0 yellow; - opacity: 0.3; -} -#PDFBug .stats { - font-family: courier; - font-size: 10px; - white-space: pre; -} -#PDFBug .stats .title { - font-weight: bold; -} -#PDFBug table { - font-size: 10px; -} - -#viewer.textLayer-visible .textLayer > div, -#viewer.textLayer-hover .textLayer > div:hover { - background-color: white; - color: black; -} - -#viewer.textLayer-shadow .textLayer > div { - background-color: rgba(255,255,255, .6); - color: black; -} - -@page { - margin: 0; -} - -#printContainer { - display: none; -} - -@media print { - /* Rules for browsers that don't support mozPrintCallback. */ - #sidebarContainer, .toolbar, #loadingBox, #errorWrapper, .textLayer { - display: none; - } - - #mainContainer, #viewerContainer, .page, .page canvas { - position: static; - padding: 0; - margin: 0; - } - - .page { - float: left; - display: none; - box-shadow: none; - } - - .page[data-loaded] { - display: block; - } - - /* Rules for browsers that support mozPrintCallback */ - body[data-mozPrintCallback] #outerContainer { - display: none; - } - body[data-mozPrintCallback] #printContainer { - display: block; - } - #printContainer canvas { - position: relative; - top: 0; - left: 0; - } -} - -@media all and (max-width: 950px) { - html[dir='ltr'] #outerContainer.sidebarMoving .outerCenter, - html[dir='ltr'] #outerContainer.sidebarOpen .outerCenter { - float: left; - left: 180px; - } - html[dir='rtl'] #outerContainer.sidebarMoving .outerCenter, - html[dir='rtl'] #outerContainer.sidebarOpen .outerCenter { - float: right; - right: 180px; - } -} - -@media all and (max-width: 770px) { - #sidebarContainer { - top: 33px; - z-index: 100; - } - #sidebarContent { - top: 32px; - background-color: hsla(0,0%,0%,.7); - } - - html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer { - left: 0px; - } - html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer { - right: 0px; - } - - html[dir='ltr'] .outerCenter { - float: left; - left: 180px; - } - html[dir='rtl'] .outerCenter { - float: right; - right: 180px; - } -} - -@media all and (max-width: 600px) { - .hiddenSmallView { - display: none; - } - html[dir='ltr'] .outerCenter { - left: 156px; - } - html[dir='rtr'] .outerCenter { - right: 156px; - } - .toolbarButtonSpacer { - width: 0; - } -} - -@media all and (max-width: 500px) { - #scaleSelectContainer, #pageNumberLabel { - display: none; - } -} - diff --git a/mediagoblin/static/extlib/tinymce b/mediagoblin/static/extlib/tinymce new file mode 120000 index 00000000..debf6e2e --- /dev/null +++ b/mediagoblin/static/extlib/tinymce @@ -0,0 +1 @@ +../../../extlib/tinymce
\ No newline at end of file diff --git a/mediagoblin/static/images/frontpage_image.png b/mediagoblin/static/images/frontpage_image.png Binary files differdeleted file mode 100644 index 689eb2c2..00000000 --- a/mediagoblin/static/images/frontpage_image.png +++ /dev/null diff --git a/mediagoblin/static/images/home_goblin.png b/mediagoblin/static/images/home_goblin.png Binary files differnew file mode 100644 index 00000000..5ba9afeb --- /dev/null +++ b/mediagoblin/static/images/home_goblin.png diff --git a/mediagoblin/static/images/home_goblin.xcf b/mediagoblin/static/images/home_goblin.xcf Binary files differnew file mode 100644 index 00000000..e75d6b5f --- /dev/null +++ b/mediagoblin/static/images/home_goblin.xcf diff --git a/mediagoblin/static/images/icon_clipboard.png b/mediagoblin/static/images/icon_clipboard.png Binary files differnew file mode 100644 index 00000000..6f94498b --- /dev/null +++ b/mediagoblin/static/images/icon_clipboard.png diff --git a/mediagoblin/static/images/icon_clipboard_alert.png b/mediagoblin/static/images/icon_clipboard_alert.png Binary files differnew file mode 100644 index 00000000..952c588d --- /dev/null +++ b/mediagoblin/static/images/icon_clipboard_alert.png diff --git a/mediagoblin/static/images/media_thumbs/blogpost.jpg b/mediagoblin/static/images/media_thumbs/blogpost.jpg Binary files differnew file mode 100644 index 00000000..c6c68678 --- /dev/null +++ b/mediagoblin/static/images/media_thumbs/blogpost.jpg diff --git a/mediagoblin/static/js/comment_show.js b/mediagoblin/static/js/comment_show.js index c5ccee66..df3c1093 100644 --- a/mediagoblin/static/js/comment_show.js +++ b/mediagoblin/static/js/comment_show.js @@ -15,12 +15,25 @@ * 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/>. */ +var content=""; +function previewComment(){ + if ($('#comment_content').val() && (content != $('#comment_content').val())) { + content = $('#comment_content').val(); + $.post($('#previewURL').val(),$('#form_comment').serialize(), + function(data){ + preview = JSON.parse(data) + $('#comment_preview').replaceWith("<div id=comment_preview><h3>" + $('#previewText').val() +"</h3><br />" + preview.content + + "<hr style='border: 1px solid #333;' /></div>"); + }); + } +} $(document).ready(function(){ $('#form_comment').hide(); $('#button_addcomment').click(function(){ $(this).fadeOut('fast'); $('#form_comment').slideDown(function(){ + setInterval("previewComment()",1000); $('#comment_content').focus(); }); }); diff --git a/mediagoblin/static/js/file_size.js b/mediagoblin/static/js/file_size.js new file mode 100644 index 00000000..2238ef89 --- /dev/null +++ b/mediagoblin/static/js/file_size.js @@ -0,0 +1,45 @@ +/** + * GNU MediaGoblin -- federated, autonomous media hosting + * Copyright (C) 2011, 2012 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/>. + */ + +$(document).ready(function(){ + var file = document.getElementById('file'); + var uploaded = parseInt(document.getElementById('uploaded').value); + var upload_limit = parseInt(document.getElementById('upload_limit').value); + var max_file_size = parseInt(document.getElementById('max_file_size').value); + + file.onchange = function() { + var file_size = file.files[0].size / (1024.0 * 1024); + + if (file_size >= max_file_size) { + $('#file').after('<p id="file_size_error" class="form_field_error">Sorry, the file size is too big.</p>'); + } + else if (document.getElementById('file_size_error')) { + $('#file_size_error').hide(); + } + + if (upload_limit) { + if ( uploaded + file_size >= upload_limit) { + $('#file').after('<p id="upload_limit_error" class="form_field_error">Sorry, uploading this file will put you over your upload limit.</p>'); + } + else if (document.getElementById('upload_limit_error')) { + $('#upload_limit_error').hide(); + console.log(file_size >= max_file_size); + } + } + }; +}); diff --git a/mediagoblin/static/js/notifications.js b/mediagoblin/static/js/notifications.js new file mode 100644 index 00000000..78694f59 --- /dev/null +++ b/mediagoblin/static/js/notifications.js @@ -0,0 +1,49 @@ +'use strict'; +/** + * GNU MediaGoblin -- federated, autonomous media hosting + * Copyright (C) 2011, 2012 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/>. + */ + +var notifications = {}; + +(function (n) { + n._base = '/'; + n._endpoint = 'notifications/json'; + + n.init = function () { + $('.notification-gem').on('click', function () { + $('.header_dropdown_down:visible').click(); + }); + } + +})(notifications) + +$(document).ready(function () { + notifications.init(); + + var mark_all_comments_seen = document.getElementById('mark_all_comments_seen'); + + if (mark_all_comments_seen) { + mark_all_comments_seen.href = '#'; + mark_all_comments_seen.onclick = function() { + $.ajax({ + type: 'GET', + url: mark_all_comments_seen_url, + success: function(res, status, xhr) { window.location.reload(); }, + }); + } + } +}); diff --git a/mediagoblin/static/js/pdf_viewer.js b/mediagoblin/static/js/pdf_viewer.js deleted file mode 100644 index 79c1e708..00000000 --- a/mediagoblin/static/js/pdf_viewer.js +++ /dev/null @@ -1,3615 +0,0 @@ -/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ -/* Copyright 2012 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* globals PDFJS, PDFBug, FirefoxCom, Stats */ - -'use strict'; - -var DEFAULT_SCALE = 'auto'; -var DEFAULT_SCALE_DELTA = 1.1; -var UNKNOWN_SCALE = 0; -var CACHE_SIZE = 20; -var CSS_UNITS = 96.0 / 72.0; -var SCROLLBAR_PADDING = 40; -var VERTICAL_PADDING = 5; -var MIN_SCALE = 0.25; -var MAX_SCALE = 4.0; -var IMAGE_DIR = './images/'; -var SETTINGS_MEMORY = 20; -var ANNOT_MIN_SIZE = 10; -var RenderingStates = { - INITIAL: 0, - RUNNING: 1, - PAUSED: 2, - FINISHED: 3 -}; -var FindStates = { - FIND_FOUND: 0, - FIND_NOTFOUND: 1, - FIND_WRAPPED: 2, - FIND_PENDING: 3 -}; - -//#if (FIREFOX || MOZCENTRAL || B2G || GENERIC || CHROME) -//PDFJS.workerSrc = '../build/pdf.js'; -//#endif - -var mozL10n = document.mozL10n || document.webL10n; - -function getFileName(url) { - var anchor = url.indexOf('#'); - var query = url.indexOf('?'); - var end = Math.min( - anchor > 0 ? anchor : url.length, - query > 0 ? query : url.length); - return url.substring(url.lastIndexOf('/', end) + 1, end); -} - -function scrollIntoView(element, spot) { - // Assuming offsetParent is available (it's not available when viewer is in - // hidden iframe or object). We have to scroll: if the offsetParent is not set - // producing the error. See also animationStartedClosure. - var parent = element.offsetParent; - var offsetY = element.offsetTop + element.clientTop; - if (!parent) { - console.error('offsetParent is not set -- cannot scroll'); - return; - } - while (parent.clientHeight == parent.scrollHeight) { - offsetY += parent.offsetTop; - parent = parent.offsetParent; - if (!parent) - return; // no need to scroll - } - if (spot) - offsetY += spot.top; - parent.scrollTop = offsetY; -} - -var Cache = function cacheCache(size) { - var data = []; - this.push = function cachePush(view) { - var i = data.indexOf(view); - if (i >= 0) - data.splice(i); - data.push(view); - if (data.length > size) - data.shift().destroy(); - }; -}; - -var ProgressBar = (function ProgressBarClosure() { - - function clamp(v, min, max) { - return Math.min(Math.max(v, min), max); - } - - function ProgressBar(id, opts) { - - // Fetch the sub-elements for later - this.div = document.querySelector(id + ' .progress'); - - // Get options, with sensible defaults - this.height = opts.height || 100; - this.width = opts.width || 100; - this.units = opts.units || '%'; - - // Initialize heights - this.div.style.height = this.height + this.units; - } - - ProgressBar.prototype = { - - updateBar: function ProgressBar_updateBar() { - if (this._indeterminate) { - this.div.classList.add('indeterminate'); - return; - } - - var progressSize = this.width * this._percent / 100; - - if (this._percent > 95) - this.div.classList.add('full'); - else - this.div.classList.remove('full'); - this.div.classList.remove('indeterminate'); - - this.div.style.width = progressSize + this.units; - }, - - get percent() { - return this._percent; - }, - - set percent(val) { - this._indeterminate = isNaN(val); - this._percent = clamp(val, 0, 100); - this.updateBar(); - } - }; - - return ProgressBar; -})(); - -//#if FIREFOX || MOZCENTRAL -//#include firefoxcom.js -//#endif - -// Settings Manager - This is a utility for saving settings -// First we see if localStorage is available -// If not, we use FUEL in FF -// Use asyncStorage for B2G -var Settings = (function SettingsClosure() { -//#if !(FIREFOX || MOZCENTRAL || B2G) - var isLocalStorageEnabled = (function localStorageEnabledTest() { - // Feature test as per http://diveintohtml5.info/storage.html - // The additional localStorage call is to get around a FF quirk, see - // bug #495747 in bugzilla - try { - return 'localStorage' in window && window['localStorage'] !== null && - localStorage; - } catch (e) { - return false; - } - })(); -//#endif - - function Settings(fingerprint) { - this.fingerprint = fingerprint; - this.initializedPromise = new PDFJS.Promise(); - - var resolvePromise = (function settingsResolvePromise(db) { - this.initialize(db || '{}'); - this.initializedPromise.resolve(); - }).bind(this); - -//#if B2G -// asyncStorage.getItem('database', resolvePromise); -//#endif - -//#if FIREFOX || MOZCENTRAL -// resolvePromise(FirefoxCom.requestSync('getDatabase', null)); -//#endif - -//#if !(FIREFOX || MOZCENTRAL || B2G) - if (isLocalStorageEnabled) - resolvePromise(localStorage.getItem('database')); -//#endif - } - - Settings.prototype = { - initialize: function settingsInitialize(database) { - database = JSON.parse(database); - if (!('files' in database)) - database.files = []; - if (database.files.length >= SETTINGS_MEMORY) - database.files.shift(); - var index; - for (var i = 0, length = database.files.length; i < length; i++) { - var branch = database.files[i]; - if (branch.fingerprint == this.fingerprint) { - index = i; - break; - } - } - if (typeof index != 'number') - index = database.files.push({fingerprint: this.fingerprint}) - 1; - this.file = database.files[index]; - this.database = database; - }, - - set: function settingsSet(name, val) { - if (!this.initializedPromise.isResolved) - return; - - var file = this.file; - file[name] = val; - var database = JSON.stringify(this.database); - -//#if B2G -// asyncStorage.setItem('database', database); -//#endif - -//#if FIREFOX || MOZCENTRAL -// FirefoxCom.requestSync('setDatabase', database); -//#endif - -//#if !(FIREFOX || MOZCENTRAL || B2G) - if (isLocalStorageEnabled) - localStorage.setItem('database', database); -//#endif - }, - - get: function settingsGet(name, defaultValue) { - if (!this.initializedPromise.isResolved) - return defaultValue; - - return this.file[name] || defaultValue; - } - }; - - return Settings; -})(); - -var cache = new Cache(CACHE_SIZE); -var currentPageNumber = 1; - -var PDFFindController = { - startedTextExtraction: false, - - extractTextPromises: [], - - // If active, find results will be highlighted. - active: false, - - // Stores the text for each page. - pageContents: [], - - pageMatches: [], - - // Currently selected match. - selected: { - pageIdx: -1, - matchIdx: -1 - }, - - // Where find algorithm currently is in the document. - offset: { - pageIdx: null, - matchIdx: null - }, - - resumePageIdx: null, - - resumeCallback: null, - - state: null, - - dirtyMatch: false, - - findTimeout: null, - - initialize: function() { - var events = [ - 'find', - 'findagain', - 'findhighlightallchange', - 'findcasesensitivitychange' - ]; - - this.handleEvent = this.handleEvent.bind(this); - - for (var i = 0; i < events.length; i++) { - window.addEventListener(events[i], this.handleEvent); - } - }, - - calcFindMatch: function(pageIndex) { - var pageContent = this.pageContents[pageIndex]; - var query = this.state.query; - var caseSensitive = this.state.caseSensitive; - var queryLen = query.length; - - if (queryLen === 0) { - // Do nothing the matches should be wiped out already. - return; - } - - if (!caseSensitive) { - pageContent = pageContent.toLowerCase(); - query = query.toLowerCase(); - } - - var matches = []; - - var matchIdx = -queryLen; - while (true) { - matchIdx = pageContent.indexOf(query, matchIdx + queryLen); - if (matchIdx === -1) { - break; - } - - matches.push(matchIdx); - } - this.pageMatches[pageIndex] = matches; - this.updatePage(pageIndex); - if (this.resumePageIdx === pageIndex) { - var callback = this.resumeCallback; - this.resumePageIdx = null; - this.resumeCallback = null; - callback(); - } - }, - - extractText: function() { - if (this.startedTextExtraction) { - return; - } - this.startedTextExtraction = true; - - this.pageContents = []; - for (var i = 0, ii = PDFView.pdfDocument.numPages; i < ii; i++) { - this.extractTextPromises.push(new PDFJS.Promise()); - } - - var self = this; - function extractPageText(pageIndex) { - PDFView.pages[pageIndex].getTextContent().then( - function textContentResolved(data) { - // Build the find string. - var bidiTexts = data.bidiTexts; - var str = ''; - - for (var i = 0; i < bidiTexts.length; i++) { - str += bidiTexts[i].str; - } - - // Store the pageContent as a string. - self.pageContents.push(str); - - self.extractTextPromises[pageIndex].resolve(pageIndex); - if ((pageIndex + 1) < PDFView.pages.length) - extractPageText(pageIndex + 1); - } - ); - } - extractPageText(0); - return this.extractTextPromise; - }, - - handleEvent: function(e) { - if (this.state === null || e.type !== 'findagain') { - this.dirtyMatch = true; - } - this.state = e.detail; - this.updateUIState(FindStates.FIND_PENDING); - - this.extractText(); - - clearTimeout(this.findTimeout); - if (e.type === 'find') { - // Only trigger the find action after 250ms of silence. - this.findTimeout = setTimeout(this.nextMatch.bind(this), 250); - } else { - this.nextMatch(); - } - }, - - updatePage: function(idx) { - var page = PDFView.pages[idx]; - - if (this.selected.pageIdx === idx) { - // If the page is selected, scroll the page into view, which triggers - // rendering the page, which adds the textLayer. Once the textLayer is - // build, it will scroll onto the selected match. - page.scrollIntoView(); - } - - if (page.textLayer) { - page.textLayer.updateMatches(); - } - }, - - nextMatch: function() { - var pages = PDFView.pages; - var previous = this.state.findPrevious; - var numPages = PDFView.pages.length; - - this.active = true; - - if (this.dirtyMatch) { - // Need to recalculate the matches, reset everything. - this.dirtyMatch = false; - this.selected.pageIdx = this.selected.matchIdx = -1; - this.offset.pageIdx = previous ? numPages - 1 : 0; - this.offset.matchIdx = null; - this.hadMatch = false; - this.resumeCallback = null; - this.resumePageIdx = null; - this.pageMatches = []; - var self = this; - - for (var i = 0; i < numPages; i++) { - // Wipe out any previous highlighted matches. - this.updatePage(i); - - // As soon as the text is extracted start finding the matches. - this.extractTextPromises[i].onData(function(pageIdx) { - // Use a timeout since all the pages may already be extracted and we - // want to start highlighting before finding all the matches. - setTimeout(function() { - self.calcFindMatch(pageIdx); - }); - }); - } - } - - // If there's no query there's no point in searching. - if (this.state.query === '') { - this.updateUIState(FindStates.FIND_FOUND); - return; - } - - // If we're waiting on a page, we return since we can't do anything else. - if (this.resumeCallback) { - return; - } - - var offset = this.offset; - // If there's already a matchIdx that means we are iterating through a - // page's matches. - if (offset.matchIdx !== null) { - var numPageMatches = this.pageMatches[offset.pageIdx].length; - if ((!previous && offset.matchIdx + 1 < numPageMatches) || - (previous && offset.matchIdx > 0)) { - // The simple case, we just have advance the matchIdx to select the next - // match on the page. - this.hadMatch = true; - offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1; - this.updateMatch(true); - return; - } - // We went beyond the current page's matches, so we advance to the next - // page. - this.advanceOffsetPage(previous); - } - // Start searching through the page. - this.nextPageMatch(); - }, - - nextPageMatch: function() { - if (this.resumePageIdx !== null) - console.error('There can only be one pending page.'); - - var matchesReady = function(matches) { - var offset = this.offset; - var numMatches = matches.length; - var previous = this.state.findPrevious; - if (numMatches) { - // There were matches for the page, so initialize the matchIdx. - this.hadMatch = true; - offset.matchIdx = previous ? numMatches - 1 : 0; - this.updateMatch(true); - } else { - // No matches attempt to search the next page. - this.advanceOffsetPage(previous); - if (offset.wrapped) { - offset.matchIdx = null; - if (!this.hadMatch) { - // No point in wrapping there were no matches. - this.updateMatch(false); - return; - } - } - // Search the next page. - this.nextPageMatch(); - } - }.bind(this); - - var pageIdx = this.offset.pageIdx; - var pageMatches = this.pageMatches; - if (!pageMatches[pageIdx]) { - // The matches aren't ready setup a callback so we can be notified, - // when they are ready. - this.resumeCallback = function() { - matchesReady(pageMatches[pageIdx]); - }; - this.resumePageIdx = pageIdx; - return; - } - // The matches are finished already. - matchesReady(pageMatches[pageIdx]); - }, - - advanceOffsetPage: function(previous) { - var offset = this.offset; - var numPages = this.extractTextPromises.length; - offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1; - offset.matchIdx = null; - if (offset.pageIdx >= numPages || offset.pageIdx < 0) { - offset.pageIdx = previous ? numPages - 1 : 0; - offset.wrapped = true; - return; - } - }, - - updateMatch: function(found) { - var state = FindStates.FIND_NOTFOUND; - var wrapped = this.offset.wrapped; - this.offset.wrapped = false; - if (found) { - var previousPage = this.selected.pageIdx; - this.selected.pageIdx = this.offset.pageIdx; - this.selected.matchIdx = this.offset.matchIdx; - state = wrapped ? FindStates.FIND_WRAPPED : FindStates.FIND_FOUND; - // Update the currently selected page to wipe out any selected matches. - if (previousPage !== -1 && previousPage !== this.selected.pageIdx) { - this.updatePage(previousPage); - } - } - this.updateUIState(state, this.state.findPrevious); - if (this.selected.pageIdx !== -1) { - this.updatePage(this.selected.pageIdx, true); - } - }, - - updateUIState: function(state, previous) { - if (PDFView.supportsIntegratedFind) { - FirefoxCom.request('updateFindControlState', - {result: state, findPrevious: previous}); - return; - } - PDFFindBar.updateUIState(state, previous); - } -}; - -var PDFFindBar = { - // TODO: Enable the FindBar *AFTER* the pagesPromise in the load function - // got resolved - - opened: false, - - initialize: function() { - this.bar = document.getElementById('findbar'); - this.toggleButton = document.getElementById('viewFind'); - this.findField = document.getElementById('findInput'); - this.highlightAll = document.getElementById('findHighlightAll'); - this.caseSensitive = document.getElementById('findMatchCase'); - this.findMsg = document.getElementById('findMsg'); - this.findStatusIcon = document.getElementById('findStatusIcon'); - - var self = this; - this.toggleButton.addEventListener('click', function() { - self.toggle(); - }); - - this.findField.addEventListener('input', function() { - self.dispatchEvent(''); - }); - - this.bar.addEventListener('keydown', function(evt) { - switch (evt.keyCode) { - case 13: // Enter - if (evt.target === self.findField) { - self.dispatchEvent('again', evt.shiftKey); - } - break; - case 27: // Escape - self.close(); - break; - } - }); - - document.getElementById('findPrevious').addEventListener('click', - function() { self.dispatchEvent('again', true); } - ); - - document.getElementById('findNext').addEventListener('click', function() { - self.dispatchEvent('again', false); - }); - - this.highlightAll.addEventListener('click', function() { - self.dispatchEvent('highlightallchange'); - }); - - this.caseSensitive.addEventListener('click', function() { - self.dispatchEvent('casesensitivitychange'); - }); - }, - - dispatchEvent: function(aType, aFindPrevious) { - var event = document.createEvent('CustomEvent'); - event.initCustomEvent('find' + aType, true, true, { - query: this.findField.value, - caseSensitive: this.caseSensitive.checked, - highlightAll: this.highlightAll.checked, - findPrevious: aFindPrevious - }); - return window.dispatchEvent(event); - }, - - updateUIState: function(state, previous) { - var notFound = false; - var findMsg = ''; - var status = ''; - - switch (state) { - case FindStates.FIND_FOUND: - break; - - case FindStates.FIND_PENDING: - status = 'pending'; - break; - - case FindStates.FIND_NOTFOUND: - findMsg = mozL10n.get('find_not_found', null, 'Phrase not found'); - notFound = true; - break; - - case FindStates.FIND_WRAPPED: - if (previous) { - findMsg = mozL10n.get('find_reached_top', null, - 'Reached top of document, continued from bottom'); - } else { - findMsg = mozL10n.get('find_reached_bottom', null, - 'Reached end of document, continued from top'); - } - break; - } - - if (notFound) { - this.findField.classList.add('notFound'); - } else { - this.findField.classList.remove('notFound'); - } - - this.findField.setAttribute('data-status', status); - this.findMsg.textContent = findMsg; - }, - - open: function() { - if (this.opened) return; - - this.opened = true; - this.toggleButton.classList.add('toggled'); - this.bar.classList.remove('hidden'); - this.findField.select(); - this.findField.focus(); - }, - - close: function() { - if (!this.opened) return; - - this.opened = false; - this.toggleButton.classList.remove('toggled'); - this.bar.classList.add('hidden'); - - PDFFindController.active = false; - }, - - toggle: function() { - if (this.opened) { - this.close(); - } else { - this.open(); - } - } -}; - -var PDFView = { - pages: [], - thumbnails: [], - currentScale: UNKNOWN_SCALE, - currentScaleValue: null, - initialBookmark: document.location.hash.substring(1), - startedTextExtraction: false, - pageText: [], - container: null, - thumbnailContainer: null, - initialized: false, - fellback: false, - pdfDocument: null, - sidebarOpen: false, - pageViewScroll: null, - thumbnailViewScroll: null, - isFullscreen: false, - previousScale: null, - pageRotation: 0, - mouseScrollTimeStamp: 0, - mouseScrollDelta: 0, - lastScroll: 0, - previousPageNumber: 1, - - // called once when the document is loaded - initialize: function pdfViewInitialize() { - var self = this; - var container = this.container = document.getElementById('viewerContainer'); - this.pageViewScroll = {}; - this.watchScroll(container, this.pageViewScroll, updateViewarea); - - var thumbnailContainer = this.thumbnailContainer = - document.getElementById('thumbnailView'); - this.thumbnailViewScroll = {}; - this.watchScroll(thumbnailContainer, this.thumbnailViewScroll, - this.renderHighestPriority.bind(this)); - - PDFFindBar.initialize(); - PDFFindController.initialize(); - - this.initialized = true; - container.addEventListener('scroll', function() { - self.lastScroll = Date.now(); - }, false); - }, - - getPage: function pdfViewGetPage(n) { - return this.pdfDocument.getPage(n); - }, - - // Helper function to keep track whether a div was scrolled up or down and - // then call a callback. - watchScroll: function pdfViewWatchScroll(viewAreaElement, state, callback) { - state.down = true; - state.lastY = viewAreaElement.scrollTop; - viewAreaElement.addEventListener('scroll', function webViewerScroll(evt) { - var currentY = viewAreaElement.scrollTop; - var lastY = state.lastY; - if (currentY > lastY) - state.down = true; - else if (currentY < lastY) - state.down = false; - // else do nothing and use previous value - state.lastY = currentY; - callback(); - }, true); - }, - - setScale: function pdfViewSetScale(val, resetAutoSettings, noScroll) { - if (val == this.currentScale) - return; - - var pages = this.pages; - for (var i = 0; i < pages.length; i++) - pages[i].update(val * CSS_UNITS); - - if (!noScroll && this.currentScale != val) - this.pages[this.page - 1].scrollIntoView(); - this.currentScale = val; - - var event = document.createEvent('UIEvents'); - event.initUIEvent('scalechange', false, false, window, 0); - event.scale = val; - event.resetAutoSettings = resetAutoSettings; - window.dispatchEvent(event); - }, - - parseScale: function pdfViewParseScale(value, resetAutoSettings, noScroll) { - if ('custom' == value) - return; - - var scale = parseFloat(value); - this.currentScaleValue = value; - if (scale) { - this.setScale(scale, true, noScroll); - return; - } - - var container = this.container; - var currentPage = this.pages[this.page - 1]; - if (!currentPage) { - return; - } - - var pageWidthScale = (container.clientWidth - SCROLLBAR_PADDING) / - currentPage.width * currentPage.scale / CSS_UNITS; - var pageHeightScale = (container.clientHeight - VERTICAL_PADDING) / - currentPage.height * currentPage.scale / CSS_UNITS; - switch (value) { - case 'page-actual': - scale = 1; - break; - case 'page-width': - scale = pageWidthScale; - break; - case 'page-height': - scale = pageHeightScale; - break; - case 'page-fit': - scale = Math.min(pageWidthScale, pageHeightScale); - break; - case 'auto': - scale = Math.min(1.0, pageWidthScale); - break; - } - this.setScale(scale, resetAutoSettings, noScroll); - - selectScaleOption(value); - }, - - zoomIn: function pdfViewZoomIn() { - var newScale = (this.currentScale * DEFAULT_SCALE_DELTA).toFixed(2); - newScale = Math.ceil(newScale * 10) / 10; - newScale = Math.min(MAX_SCALE, newScale); - this.parseScale(newScale, true); - }, - - zoomOut: function pdfViewZoomOut() { - var newScale = (this.currentScale / DEFAULT_SCALE_DELTA).toFixed(2); - newScale = Math.floor(newScale * 10) / 10; - newScale = Math.max(MIN_SCALE, newScale); - this.parseScale(newScale, true); - }, - - set page(val) { - var pages = this.pages; - var input = document.getElementById('pageNumber'); - var event = document.createEvent('UIEvents'); - event.initUIEvent('pagechange', false, false, window, 0); - - if (!(0 < val && val <= pages.length)) { - this.previousPageNumber = val; - event.pageNumber = this.page; - window.dispatchEvent(event); - return; - } - - pages[val - 1].updateStats(); - this.previousPageNumber = currentPageNumber; - currentPageNumber = val; - event.pageNumber = val; - window.dispatchEvent(event); - - // checking if the this.page was called from the updateViewarea function: - // avoiding the creation of two "set page" method (internal and public) - if (updateViewarea.inProgress) - return; - - // Avoid scrolling the first page during loading - if (this.loading && val == 1) - return; - - pages[val - 1].scrollIntoView(); - }, - - get page() { - return currentPageNumber; - }, - - get supportsPrinting() { - var canvas = document.createElement('canvas'); - var value = 'mozPrintCallback' in canvas; - // shadow - Object.defineProperty(this, 'supportsPrinting', { value: value, - enumerable: true, - configurable: true, - writable: false }); - return value; - }, - - get supportsFullscreen() { - var doc = document.documentElement; - var support = doc.requestFullscreen || doc.mozRequestFullScreen || - doc.webkitRequestFullScreen; - - // Disable fullscreen button if we're in an iframe - if (!!window.frameElement) - support = false; - - Object.defineProperty(this, 'supportsFullScreen', { value: support, - enumerable: true, - configurable: true, - writable: false }); - return support; - }, - - get supportsIntegratedFind() { - var support = false; -//#if !(FIREFOX || MOZCENTRAL) -//#else -// support = FirefoxCom.requestSync('supportsIntegratedFind'); -//#endif - Object.defineProperty(this, 'supportsIntegratedFind', { value: support, - enumerable: true, - configurable: true, - writable: false }); - return support; - }, - - get supportsDocumentFonts() { - var support = true; -//#if !(FIREFOX || MOZCENTRAL) -//#else -// support = FirefoxCom.requestSync('supportsDocumentFonts'); -//#endif - Object.defineProperty(this, 'supportsDocumentFonts', { value: support, - enumerable: true, - configurable: true, - writable: false }); - return support; - }, - - get isHorizontalScrollbarEnabled() { - var div = document.getElementById('viewerContainer'); - return div.scrollWidth > div.clientWidth; - }, - - initPassiveLoading: function pdfViewInitPassiveLoading() { - if (!PDFView.loadingBar) { - PDFView.loadingBar = new ProgressBar('#loadingBar', {}); - } - - window.addEventListener('message', function window_message(e) { - var args = e.data; - - if (typeof args !== 'object' || !('pdfjsLoadAction' in args)) - return; - switch (args.pdfjsLoadAction) { - case 'progress': - PDFView.progress(args.loaded / args.total); - break; - case 'complete': - if (!args.data) { - PDFView.error(mozL10n.get('loading_error', null, - 'An error occurred while loading the PDF.'), e); - break; - } - PDFView.open(args.data, 0); - break; - } - }); - FirefoxCom.requestSync('initPassiveLoading', null); - }, - - setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) { - this.url = url; - try { - this.setTitle(decodeURIComponent(getFileName(url)) || url); - } catch (e) { - // decodeURIComponent may throw URIError, - // fall back to using the unprocessed url in that case - this.setTitle(url); - } - }, - - setTitle: function pdfViewSetTitle(title) { - document.title = title; -//#if B2G -// document.getElementById('activityTitle').textContent = title; -//#endif - }, - - open: function pdfViewOpen(url, scale, password) { - var parameters = {password: password}; - if (typeof url === 'string') { // URL - this.setTitleUsingUrl(url); - parameters.url = url; - } else if (url && 'byteLength' in url) { // ArrayBuffer - parameters.data = url; - } - - if (!PDFView.loadingBar) { - PDFView.loadingBar = new ProgressBar('#loadingBar', {}); - } - - this.pdfDocument = null; - var self = this; - self.loading = true; - PDFJS.getDocument(parameters).then( - function getDocumentCallback(pdfDocument) { - self.load(pdfDocument, scale); - self.loading = false; - }, - function getDocumentError(message, exception) { - if (exception && exception.name === 'PasswordException') { - if (exception.code === 'needpassword') { - var promptString = mozL10n.get('request_password', null, - 'PDF is protected by a password:'); - password = prompt(promptString); - if (password && password.length > 0) { - return PDFView.open(url, scale, password); - } - } - } - - var loadingErrorMessage = mozL10n.get('loading_error', null, - 'An error occurred while loading the PDF.'); - - if (exception && exception.name === 'InvalidPDFException') { - // change error message also for other builds - var loadingErrorMessage = mozL10n.get('invalid_file_error', null, - 'Invalid or corrupted PDF file.'); -//#if B2G -// window.alert(loadingErrorMessage); -// return window.close(); -//#endif - } - - if (exception && exception.name === 'MissingPDFException') { - // special message for missing PDF's - var loadingErrorMessage = mozL10n.get('missing_file_error', null, - 'Missing PDF file.'); - -//#if B2G -// window.alert(loadingErrorMessage); -// return window.close(); -//#endif - } - - var loadingIndicator = document.getElementById('loading'); - loadingIndicator.textContent = mozL10n.get('loading_error_indicator', - null, 'Error'); - var moreInfo = { - message: message - }; - self.error(loadingErrorMessage, moreInfo); - self.loading = false; - }, - function getDocumentProgress(progressData) { - self.progress(progressData.loaded / progressData.total); - } - ); - }, - - download: function pdfViewDownload() { - function noData() { - FirefoxCom.request('download', { originalUrl: url }); - } - var url = this.url.split('#')[0]; -//#if !(FIREFOX || MOZCENTRAL) - url += '#pdfjs.action=download'; - window.open(url, '_parent'); -//#else -// // Document isn't ready just try to download with the url. -// if (!this.pdfDocument) { -// noData(); -// return; -// } -// this.pdfDocument.getData().then( -// function getDataSuccess(data) { -// var blob = PDFJS.createBlob(data.buffer, 'application/pdf'); -// var blobUrl = window.URL.createObjectURL(blob); -// -// FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url }, -// function response(err) { -// if (err) { -// // This error won't really be helpful because it's likely the -// // fallback won't work either (or is already open). -// PDFView.error('PDF failed to download.'); -// } -// window.URL.revokeObjectURL(blobUrl); -// } -// ); -// }, -// noData // Error occurred try downloading with just the url. -// ); -//#endif - }, - - fallback: function pdfViewFallback() { -//#if !(FIREFOX || MOZCENTRAL) -// return; -//#else -// // Only trigger the fallback once so we don't spam the user with messages -// // for one PDF. -// if (this.fellback) -// return; -// this.fellback = true; -// var url = this.url.split('#')[0]; -// FirefoxCom.request('fallback', url, function response(download) { -// if (!download) -// return; -// PDFView.download(); -// }); -//#endif - }, - - navigateTo: function pdfViewNavigateTo(dest) { - if (typeof dest === 'string') - dest = this.destinations[dest]; - if (!(dest instanceof Array)) - return; // invalid destination - // dest array looks like that: <page-ref> </XYZ|FitXXX> <args..> - var destRef = dest[0]; - var pageNumber = destRef instanceof Object ? - this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : (destRef + 1); - if (pageNumber > this.pages.length) - pageNumber = this.pages.length; - if (pageNumber) { - this.page = pageNumber; - var currentPage = this.pages[pageNumber - 1]; - if (!this.isFullscreen) { // Avoid breaking fullscreen mode. - currentPage.scrollIntoView(dest); - } - } - }, - - getDestinationHash: function pdfViewGetDestinationHash(dest) { - if (typeof dest === 'string') - return PDFView.getAnchorUrl('#' + escape(dest)); - if (dest instanceof Array) { - var destRef = dest[0]; // see navigateTo method for dest format - var pageNumber = destRef instanceof Object ? - this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : - (destRef + 1); - if (pageNumber) { - var pdfOpenParams = PDFView.getAnchorUrl('#page=' + pageNumber); - var destKind = dest[1]; - if (typeof destKind === 'object' && 'name' in destKind && - destKind.name == 'XYZ') { - var scale = (dest[4] || this.currentScale); - pdfOpenParams += '&zoom=' + (scale * 100); - if (dest[2] || dest[3]) { - pdfOpenParams += ',' + (dest[2] || 0) + ',' + (dest[3] || 0); - } - } - return pdfOpenParams; - } - } - return ''; - }, - - /** - * For the firefox extension we prefix the full url on anchor links so they - * don't come up as resource:// urls and so open in new tab/window works. - * @param {String} anchor The anchor hash include the #. - */ - getAnchorUrl: function getAnchorUrl(anchor) { -//#if !(FIREFOX || MOZCENTRAL) - return anchor; -//#else -// return this.url.split('#')[0] + anchor; -//#endif - }, - - /** - * Returns scale factor for the canvas. It makes sense for the HiDPI displays. - * @return {Object} The object with horizontal (sx) and vertical (sy) - scales. The scaled property is set to false if scaling is - not required, true otherwise. - */ - getOutputScale: function pdfViewGetOutputDPI() { - var pixelRatio = 'devicePixelRatio' in window ? window.devicePixelRatio : 1; - return { - sx: pixelRatio, - sy: pixelRatio, - scaled: pixelRatio != 1 - }; - }, - - /** - * Show the error box. - * @param {String} message A message that is human readable. - * @param {Object} moreInfo (optional) Further information about the error - * that is more technical. Should have a 'message' - * and optionally a 'stack' property. - */ - error: function pdfViewError(message, moreInfo) { - var moreInfoText = mozL10n.get('error_version_info', - {version: PDFJS.version || '?', build: PDFJS.build || '?'}, - 'PDF.js v{{version}} (build: {{build}})') + '\n'; - if (moreInfo) { - moreInfoText += - mozL10n.get('error_message', {message: moreInfo.message}, - 'Message: {{message}}'); - if (moreInfo.stack) { - moreInfoText += '\n' + - mozL10n.get('error_stack', {stack: moreInfo.stack}, - 'Stack: {{stack}}'); - } else { - if (moreInfo.filename) { - moreInfoText += '\n' + - mozL10n.get('error_file', {file: moreInfo.filename}, - 'File: {{file}}'); - } - if (moreInfo.lineNumber) { - moreInfoText += '\n' + - mozL10n.get('error_line', {line: moreInfo.lineNumber}, - 'Line: {{line}}'); - } - } - } - - var loadingBox = document.getElementById('loadingBox'); - loadingBox.setAttribute('hidden', 'true'); - -//#if !(FIREFOX || MOZCENTRAL) - var errorWrapper = document.getElementById('errorWrapper'); - errorWrapper.removeAttribute('hidden'); - - var errorMessage = document.getElementById('errorMessage'); - errorMessage.textContent = message; - - var closeButton = document.getElementById('errorClose'); - closeButton.onclick = function() { - errorWrapper.setAttribute('hidden', 'true'); - }; - - var errorMoreInfo = document.getElementById('errorMoreInfo'); - var moreInfoButton = document.getElementById('errorShowMore'); - var lessInfoButton = document.getElementById('errorShowLess'); - moreInfoButton.onclick = function() { - errorMoreInfo.removeAttribute('hidden'); - moreInfoButton.setAttribute('hidden', 'true'); - lessInfoButton.removeAttribute('hidden'); - }; - lessInfoButton.onclick = function() { - errorMoreInfo.setAttribute('hidden', 'true'); - moreInfoButton.removeAttribute('hidden'); - lessInfoButton.setAttribute('hidden', 'true'); - }; - moreInfoButton.removeAttribute('hidden'); - lessInfoButton.setAttribute('hidden', 'true'); - errorMoreInfo.value = moreInfoText; - - errorMoreInfo.rows = moreInfoText.split('\n').length - 1; -//#else -// console.error(message + '\n' + moreInfoText); -// this.fallback(); -//#endif - }, - - progress: function pdfViewProgress(level) { - var percent = Math.round(level * 100); - PDFView.loadingBar.percent = percent; - }, - - load: function pdfViewLoad(pdfDocument, scale) { - function bindOnAfterDraw(pageView, thumbnailView) { - // when page is painted, using the image as thumbnail base - pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() { - thumbnailView.setImage(pageView.canvas); - }; - } - - this.pdfDocument = pdfDocument; - - var errorWrapper = document.getElementById('errorWrapper'); - errorWrapper.setAttribute('hidden', 'true'); - - var loadingBox = document.getElementById('loadingBox'); - loadingBox.setAttribute('hidden', 'true'); - var loadingIndicator = document.getElementById('loading'); - loadingIndicator.textContent = ''; - - var thumbsView = document.getElementById('thumbnailView'); - thumbsView.parentNode.scrollTop = 0; - - while (thumbsView.hasChildNodes()) - thumbsView.removeChild(thumbsView.lastChild); - - if ('_loadingInterval' in thumbsView) - clearInterval(thumbsView._loadingInterval); - - var container = document.getElementById('viewer'); - while (container.hasChildNodes()) - container.removeChild(container.lastChild); - - var pagesCount = pdfDocument.numPages; - var id = pdfDocument.fingerprint; - document.getElementById('numPages').textContent = - mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}'); - document.getElementById('pageNumber').max = pagesCount; - - PDFView.documentFingerprint = id; - var store = PDFView.store = new Settings(id); - - this.pageRotation = 0; - - var pages = this.pages = []; - this.pageText = []; - this.startedTextExtraction = false; - var pagesRefMap = this.pagesRefMap = {}; - var thumbnails = this.thumbnails = []; - - var pagesPromise = new PDFJS.Promise(); - var self = this; - - var firstPagePromise = pdfDocument.getPage(1); - - // Fetch a single page so we can get a viewport that will be the default - // viewport for all pages - firstPagePromise.then(function(pdfPage) { - var viewport = pdfPage.getViewport(scale || 1.0); - var pagePromises = []; - for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) { - var viewportClone = viewport.clone(); - var pageView = new PageView(container, pageNum, scale, - self.navigateTo.bind(self), - viewportClone); - var thumbnailView = new ThumbnailView(thumbsView, pageNum, - viewportClone); - bindOnAfterDraw(pageView, thumbnailView); - pages.push(pageView); - thumbnails.push(thumbnailView); - } - - var event = document.createEvent('CustomEvent'); - event.initCustomEvent('documentload', true, true, {}); - window.dispatchEvent(event); - - for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) { - var pagePromise = pdfDocument.getPage(pageNum); - pagePromise.then(function(pdfPage) { - var pageNum = pdfPage.pageNumber; - var pageView = pages[pageNum - 1]; - if (!pageView.pdfPage) { - // The pdfPage might already be set if we've already entered - // pageView.draw() - pageView.setPdfPage(pdfPage); - } - var thumbnailView = thumbnails[pageNum - 1]; - if (!thumbnailView.pdfPage) { - thumbnailView.setPdfPage(pdfPage); - } - - var pageRef = pdfPage.ref; - var refStr = pageRef.num + ' ' + pageRef.gen + ' R'; - pagesRefMap[refStr] = pdfPage.pageNumber; - }); - pagePromises.push(pagePromise); - } - - PDFJS.Promise.all(pagePromises).then(function(pages) { - pagesPromise.resolve(pages); - }); - }); - - var storePromise = store.initializedPromise; - PDFJS.Promise.all([firstPagePromise, storePromise]).then(function() { - var storedHash = null; - if (store.get('exists', false)) { - var pageNum = store.get('page', '1'); - var zoom = store.get('zoom', PDFView.currentScale); - var left = store.get('scrollLeft', '0'); - var top = store.get('scrollTop', '0'); - - storedHash = 'page=' + pageNum + '&zoom=' + zoom + ',' + - left + ',' + top; - } - self.setInitialView(storedHash, scale); - }); - - pagesPromise.then(function() { - if (PDFView.supportsPrinting) { - pdfDocument.getJavaScript().then(function(javaScript) { - if (javaScript.length) { - console.warn('Warning: JavaScript is not supported'); - PDFView.fallback(); - } - // Hack to support auto printing. - var regex = /\bprint\s*\(/g; - for (var i = 0, ii = javaScript.length; i < ii; i++) { - var js = javaScript[i]; - if (js && regex.test(js)) { - setTimeout(function() { - window.print(); - }); - return; - } - } - }); - } - }); - - var destinationsPromise = pdfDocument.getDestinations(); - destinationsPromise.then(function(destinations) { - self.destinations = destinations; - }); - - // outline depends on destinations and pagesRefMap - var promises = [pagesPromise, destinationsPromise, - PDFView.animationStartedPromise]; - PDFJS.Promise.all(promises).then(function() { - pdfDocument.getOutline().then(function(outline) { - self.outline = new DocumentOutlineView(outline); - }); - - // Make all navigation keys work on document load, - // unless the viewer is embedded in another page. - if (window.parent.location === window.location) { - PDFView.container.focus(); - } - }); - - pdfDocument.getMetadata().then(function(data) { - var info = data.info, metadata = data.metadata; - self.documentInfo = info; - self.metadata = metadata; - - // Provides some basic debug information - console.log('PDF ' + pdfDocument.fingerprint + ' [' + - info.PDFFormatVersion + ' ' + (info.Producer || '-') + - ' / ' + (info.Creator || '-') + ']' + - (PDFJS.version ? ' (PDF.js: ' + PDFJS.version + ')' : '')); - - var pdfTitle; - if (metadata) { - if (metadata.has('dc:title')) - pdfTitle = metadata.get('dc:title'); - } - - if (!pdfTitle && info && info['Title']) - pdfTitle = info['Title']; - - if (pdfTitle) - self.setTitle(pdfTitle + ' - ' + document.title); - - if (info.IsAcroFormPresent) { - console.warn('Warning: AcroForm/XFA is not supported'); - PDFView.fallback(); - } - }); - }, - - setInitialView: function pdfViewSetInitialView(storedHash, scale) { - // Reset the current scale, as otherwise the page's scale might not get - // updated if the zoom level stayed the same. - this.currentScale = 0; - this.currentScaleValue = null; - if (this.initialBookmark) { - this.setHash(this.initialBookmark); - this.initialBookmark = null; - } - else if (storedHash) - this.setHash(storedHash); - else if (scale) { - this.parseScale(scale, true); - this.page = 1; - } - - if (PDFView.currentScale === UNKNOWN_SCALE) { - // Scale was not initialized: invalid bookmark or scale was not specified. - // Setting the default one. - this.parseScale(DEFAULT_SCALE, true); - } - }, - - renderHighestPriority: function pdfViewRenderHighestPriority() { - // Pages have a higher priority than thumbnails, so check them first. - var visiblePages = this.getVisiblePages(); - var pageView = this.getHighestPriority(visiblePages, this.pages, - this.pageViewScroll.down); - if (pageView) { - this.renderView(pageView, 'page'); - return; - } - // No pages needed rendering so check thumbnails. - if (this.sidebarOpen) { - var visibleThumbs = this.getVisibleThumbs(); - var thumbView = this.getHighestPriority(visibleThumbs, - this.thumbnails, - this.thumbnailViewScroll.down); - if (thumbView) - this.renderView(thumbView, 'thumbnail'); - } - }, - - getHighestPriority: function pdfViewGetHighestPriority(visible, views, - scrolledDown) { - // The state has changed figure out which page has the highest priority to - // render next (if any). - // Priority: - // 1 visible pages - // 2 if last scrolled down page after the visible pages - // 2 if last scrolled up page before the visible pages - var visibleViews = visible.views; - - var numVisible = visibleViews.length; - if (numVisible === 0) { - return false; - } - for (var i = 0; i < numVisible; ++i) { - var view = visibleViews[i].view; - if (!this.isViewFinished(view)) - return view; - } - - // All the visible views have rendered, try to render next/previous pages. - if (scrolledDown) { - var nextPageIndex = visible.last.id; - // ID's start at 1 so no need to add 1. - if (views[nextPageIndex] && !this.isViewFinished(views[nextPageIndex])) - return views[nextPageIndex]; - } else { - var previousPageIndex = visible.first.id - 2; - if (views[previousPageIndex] && - !this.isViewFinished(views[previousPageIndex])) - return views[previousPageIndex]; - } - // Everything that needs to be rendered has been. - return false; - }, - - isViewFinished: function pdfViewNeedsRendering(view) { - return view.renderingState === RenderingStates.FINISHED; - }, - - // Render a page or thumbnail view. This calls the appropriate function based - // on the views state. If the view is already rendered it will return false. - renderView: function pdfViewRender(view, type) { - var state = view.renderingState; - switch (state) { - case RenderingStates.FINISHED: - return false; - case RenderingStates.PAUSED: - PDFView.highestPriorityPage = type + view.id; - view.resume(); - break; - case RenderingStates.RUNNING: - PDFView.highestPriorityPage = type + view.id; - break; - case RenderingStates.INITIAL: - PDFView.highestPriorityPage = type + view.id; - view.draw(this.renderHighestPriority.bind(this)); - break; - } - return true; - }, - - setHash: function pdfViewSetHash(hash) { - if (!hash) - return; - - if (hash.indexOf('=') >= 0) { - var params = PDFView.parseQueryString(hash); - // borrowing syntax from "Parameters for Opening PDF Files" - if ('nameddest' in params) { - PDFView.navigateTo(params.nameddest); - return; - } - if ('page' in params) { - var pageNumber = (params.page | 0) || 1; - if ('zoom' in params) { - var zoomArgs = params.zoom.split(','); // scale,left,top - // building destination array - - // If the zoom value, it has to get divided by 100. If it is a string, - // it should stay as it is. - var zoomArg = zoomArgs[0]; - var zoomArgNumber = parseFloat(zoomArg); - if (zoomArgNumber) - zoomArg = zoomArgNumber / 100; - - var dest = [null, {name: 'XYZ'}, - zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null, - zoomArgs.length > 2 ? (zoomArgs[2] | 0) : null, - zoomArg]; - var currentPage = this.pages[pageNumber - 1]; - currentPage.scrollIntoView(dest); - } else { - this.page = pageNumber; // simple page - } - } - if ('pagemode' in params) { - var toggle = document.getElementById('sidebarToggle'); - if (params.pagemode === 'thumbs' || params.pagemode === 'bookmarks') { - if (!this.sidebarOpen) { - toggle.click(); - } - this.switchSidebarView(params.pagemode === 'thumbs' ? - 'thumbs' : 'outline'); - } else if (params.pagemode === 'none' && this.sidebarOpen) { - toggle.click(); - } - } - } else if (/^\d+$/.test(hash)) // page number - this.page = hash; - else // named destination - PDFView.navigateTo(unescape(hash)); - }, - - switchSidebarView: function pdfViewSwitchSidebarView(view) { - var thumbsView = document.getElementById('thumbnailView'); - var outlineView = document.getElementById('outlineView'); - - var thumbsButton = document.getElementById('viewThumbnail'); - var outlineButton = document.getElementById('viewOutline'); - - switch (view) { - case 'thumbs': - var wasOutlineViewVisible = thumbsView.classList.contains('hidden'); - - thumbsButton.classList.add('toggled'); - outlineButton.classList.remove('toggled'); - thumbsView.classList.remove('hidden'); - outlineView.classList.add('hidden'); - - PDFView.renderHighestPriority(); - - if (wasOutlineViewVisible) { - // Ensure that the thumbnail of the current page is visible - // when switching from the outline view. - scrollIntoView(document.getElementById('thumbnailContainer' + - this.page)); - } - break; - - case 'outline': - thumbsButton.classList.remove('toggled'); - outlineButton.classList.add('toggled'); - thumbsView.classList.add('hidden'); - outlineView.classList.remove('hidden'); - - if (outlineButton.getAttribute('disabled')) - return; - break; - } - }, - - getVisiblePages: function pdfViewGetVisiblePages() { - if (!this.isFullscreen) { - return this.getVisibleElements(this.container, this.pages, true); - } else { - // The algorithm in getVisibleElements is broken in fullscreen mode. - var visible = [], page = this.page; - var currentPage = this.pages[page - 1]; - visible.push({ id: currentPage.id, view: currentPage }); - - return { first: currentPage, last: currentPage, views: visible}; - } - }, - - getVisibleThumbs: function pdfViewGetVisibleThumbs() { - return this.getVisibleElements(this.thumbnailContainer, this.thumbnails); - }, - - // Generic helper to find out what elements are visible within a scroll pane. - getVisibleElements: function pdfViewGetVisibleElements( - scrollEl, views, sortByVisibility) { - var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight; - var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth; - - var visible = [], view; - var currentHeight, viewHeight, hiddenHeight, percentHeight; - var currentWidth, viewWidth; - for (var i = 0, ii = views.length; i < ii; ++i) { - view = views[i]; - currentHeight = view.el.offsetTop + view.el.clientTop; - viewHeight = view.el.clientHeight; - if ((currentHeight + viewHeight) < top) { - continue; - } - if (currentHeight > bottom) { - break; - } - currentWidth = view.el.offsetLeft + view.el.clientLeft; - viewWidth = view.el.clientWidth; - if ((currentWidth + viewWidth) < left || currentWidth > right) { - continue; - } - hiddenHeight = Math.max(0, top - currentHeight) + - Math.max(0, currentHeight + viewHeight - bottom); - percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0; - - visible.push({ id: view.id, y: currentHeight, - view: view, percent: percentHeight }); - } - - var first = visible[0]; - var last = visible[visible.length - 1]; - - if (sortByVisibility) { - visible.sort(function(a, b) { - var pc = a.percent - b.percent; - if (Math.abs(pc) > 0.001) { - return -pc; - } - return a.id - b.id; // ensure stability - }); - } - return {first: first, last: last, views: visible}; - }, - - // Helper function to parse query string (e.g. ?param1=value&parm2=...). - parseQueryString: function pdfViewParseQueryString(query) { - var parts = query.split('&'); - var params = {}; - for (var i = 0, ii = parts.length; i < parts.length; ++i) { - var param = parts[i].split('='); - var key = param[0]; - var value = param.length > 1 ? param[1] : null; - params[unescape(key)] = unescape(value); - } - return params; - }, - - beforePrint: function pdfViewSetupBeforePrint() { - if (!this.supportsPrinting) { - var printMessage = mozL10n.get('printing_not_supported', null, - 'Warning: Printing is not fully supported by this browser.'); - this.error(printMessage); - return; - } - - var alertNotReady = false; - if (!this.pages.length) { - alertNotReady = true; - } else { - for (var i = 0, ii = this.pages.length; i < ii; ++i) { - if (!this.pages[i].pdfPage) { - alertNotReady = true; - break; - } - } - } - if (alertNotReady) { - var notReadyMessage = mozL10n.get('printing_not_ready', null, - 'Warning: The PDF is not fully loaded for printing.'); - window.alert(notReadyMessage); - return; - } - - var body = document.querySelector('body'); - body.setAttribute('data-mozPrintCallback', true); - for (var i = 0, ii = this.pages.length; i < ii; ++i) { - this.pages[i].beforePrint(); - } - }, - - afterPrint: function pdfViewSetupAfterPrint() { - var div = document.getElementById('printContainer'); - while (div.hasChildNodes()) - div.removeChild(div.lastChild); - }, - - fullscreen: function pdfViewFullscreen() { - var isFullscreen = document.fullscreenElement || document.mozFullScreen || - document.webkitIsFullScreen; - - if (isFullscreen) { - return false; - } - - var wrapper = document.getElementById('viewerContainer'); - if (document.documentElement.requestFullscreen) { - wrapper.requestFullscreen(); - } else if (document.documentElement.mozRequestFullScreen) { - wrapper.mozRequestFullScreen(); - } else if (document.documentElement.webkitRequestFullScreen) { - wrapper.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); - } else { - return false; - } - - this.isFullscreen = true; - var currentPage = this.pages[this.page - 1]; - this.previousScale = this.currentScaleValue; - this.parseScale('page-fit', true); - - // Wait for fullscreen to take effect - setTimeout(function() { - currentPage.scrollIntoView(); - }, 0); - - this.showPresentationControls(); - return true; - }, - - exitFullscreen: function pdfViewExitFullscreen() { - this.isFullscreen = false; - this.parseScale(this.previousScale); - this.page = this.page; - this.clearMouseScrollState(); - this.hidePresentationControls(); - - // Ensure that the thumbnail of the current page is visible - // when exiting fullscreen mode. - scrollIntoView(document.getElementById('thumbnailContainer' + this.page)); - }, - - showPresentationControls: function pdfViewShowPresentationControls() { - var DELAY_BEFORE_HIDING_CONTROLS = 3000; - var wrapper = document.getElementById('viewerContainer'); - if (this.presentationControlsTimeout) { - clearTimeout(this.presentationControlsTimeout); - } else { - wrapper.classList.add('presentationControls'); - } - this.presentationControlsTimeout = setTimeout(function hideControls() { - wrapper.classList.remove('presentationControls'); - delete PDFView.presentationControlsTimeout; - }, DELAY_BEFORE_HIDING_CONTROLS); - }, - - hidePresentationControls: function pdfViewShowPresentationControls() { - if (!this.presentationControlsTimeout) { - return; - } - clearTimeout(this.presentationControlsTimeout); - delete this.presentationControlsTimeout; - - var wrapper = document.getElementById('viewerContainer'); - wrapper.classList.remove('presentationControls'); - }, - - rotatePages: function pdfViewPageRotation(delta) { - - this.pageRotation = (this.pageRotation + 360 + delta) % 360; - - for (var i = 0, l = this.pages.length; i < l; i++) { - var page = this.pages[i]; - page.update(page.scale, this.pageRotation); - } - - for (var i = 0, l = this.thumbnails.length; i < l; i++) { - var thumb = this.thumbnails[i]; - thumb.update(this.pageRotation); - } - - this.parseScale(this.currentScaleValue, true); - - this.renderHighestPriority(); - - var currentPage = this.pages[this.page - 1]; - if (!currentPage) { - return; - } - - // Wait for fullscreen to take effect - setTimeout(function() { - currentPage.scrollIntoView(); - }, 0); - }, - - /** - * This function flips the page in presentation mode if the user scrolls up - * or down with large enough motion and prevents page flipping too often. - * - * @this {PDFView} - * @param {number} mouseScrollDelta The delta value from the mouse event. - */ - mouseScroll: function pdfViewMouseScroll(mouseScrollDelta) { - var MOUSE_SCROLL_COOLDOWN_TIME = 50; - - var currentTime = (new Date()).getTime(); - var storedTime = this.mouseScrollTimeStamp; - - // In case one page has already been flipped there is a cooldown time - // which has to expire before next page can be scrolled on to. - if (currentTime > storedTime && - currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) - return; - - // In case the user decides to scroll to the opposite direction than before - // clear the accumulated delta. - if ((this.mouseScrollDelta > 0 && mouseScrollDelta < 0) || - (this.mouseScrollDelta < 0 && mouseScrollDelta > 0)) - this.clearMouseScrollState(); - - this.mouseScrollDelta += mouseScrollDelta; - - var PAGE_FLIP_THRESHOLD = 120; - if (Math.abs(this.mouseScrollDelta) >= PAGE_FLIP_THRESHOLD) { - - var PageFlipDirection = { - UP: -1, - DOWN: 1 - }; - - // In fullscreen mode scroll one page at a time. - var pageFlipDirection = (this.mouseScrollDelta > 0) ? - PageFlipDirection.UP : - PageFlipDirection.DOWN; - this.clearMouseScrollState(); - var currentPage = this.page; - - // In case we are already on the first or the last page there is no need - // to do anything. - if ((currentPage == 1 && pageFlipDirection == PageFlipDirection.UP) || - (currentPage == this.pages.length && - pageFlipDirection == PageFlipDirection.DOWN)) - return; - - this.page += pageFlipDirection; - this.mouseScrollTimeStamp = currentTime; - } - }, - - /** - * This function clears the member attributes used with mouse scrolling in - * presentation mode. - * - * @this {PDFView} - */ - clearMouseScrollState: function pdfViewClearMouseScrollState() { - this.mouseScrollTimeStamp = 0; - this.mouseScrollDelta = 0; - } -}; - -var PageView = function pageView(container, id, scale, - navigateTo, defaultViewport) { - this.id = id; - - this.rotation = 0; - this.scale = scale || 1.0; - this.viewport = defaultViewport; - this.pdfPageRotate = defaultViewport.rotate; - - this.renderingState = RenderingStates.INITIAL; - this.resume = null; - - this.textContent = null; - this.textLayer = null; - - var anchor = document.createElement('a'); - anchor.name = '' + this.id; - - var div = this.el = document.createElement('div'); - div.id = 'pageContainer' + this.id; - div.className = 'page'; - div.style.width = Math.floor(this.viewport.width) + 'px'; - div.style.height = Math.floor(this.viewport.height) + 'px'; - - container.appendChild(anchor); - container.appendChild(div); - - this.setPdfPage = function pageViewSetPdfPage(pdfPage) { - this.pdfPage = pdfPage; - this.pdfPageRotate = pdfPage.rotate; - this.viewport = pdfPage.getViewport(this.scale); - this.stats = pdfPage.stats; - this.update(); - }; - - this.destroy = function pageViewDestroy() { - this.update(); - if (this.pdfPage) { - this.pdfPage.destroy(); - } - }; - - this.update = function pageViewUpdate(scale, rotation) { - this.renderingState = RenderingStates.INITIAL; - this.resume = null; - - if (typeof rotation !== 'undefined') { - this.rotation = rotation; - } - - this.scale = scale || this.scale; - - var totalRotation = (this.rotation + this.pdfPageRotate) % 360; - this.viewport = this.viewport.clone({ - scale: this.scale, - rotation: totalRotation - }); - - div.style.width = Math.floor(this.viewport.width) + 'px'; - div.style.height = Math.floor(this.viewport.height) + 'px'; - - while (div.hasChildNodes()) - div.removeChild(div.lastChild); - div.removeAttribute('data-loaded'); - - delete this.canvas; - - this.loadingIconDiv = document.createElement('div'); - this.loadingIconDiv.className = 'loadingIcon'; - div.appendChild(this.loadingIconDiv); - }; - - Object.defineProperty(this, 'width', { - get: function PageView_getWidth() { - return this.viewport.width; - }, - enumerable: true - }); - - Object.defineProperty(this, 'height', { - get: function PageView_getHeight() { - return this.viewport.height; - }, - enumerable: true - }); - - function setupAnnotations(pdfPage, viewport) { - function bindLink(link, dest) { - link.href = PDFView.getDestinationHash(dest); - link.onclick = function pageViewSetupLinksOnclick() { - if (dest) - PDFView.navigateTo(dest); - return false; - }; - } - function createElementWithStyle(tagName, item, rect) { - if (!rect) { - rect = viewport.convertToViewportRectangle(item.rect); - rect = PDFJS.Util.normalizeRect(rect); - } - var element = document.createElement(tagName); - element.style.left = Math.floor(rect[0]) + 'px'; - element.style.top = Math.floor(rect[1]) + 'px'; - element.style.width = Math.ceil(rect[2] - rect[0]) + 'px'; - element.style.height = Math.ceil(rect[3] - rect[1]) + 'px'; - return element; - } - function createTextAnnotation(item) { - var container = document.createElement('section'); - container.className = 'annotText'; - - var rect = viewport.convertToViewportRectangle(item.rect); - rect = PDFJS.Util.normalizeRect(rect); - // sanity check because of OOo-generated PDFs - if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) { - rect[3] = rect[1] + ANNOT_MIN_SIZE; - } - if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) { - rect[2] = rect[0] + (rect[3] - rect[1]); // make it square - } - var image = createElementWithStyle('img', item, rect); - var iconName = item.name; - image.src = IMAGE_DIR + 'annotation-' + - iconName.toLowerCase() + '.svg'; - image.alt = mozL10n.get('text_annotation_type', {type: iconName}, - '[{{type}} Annotation]'); - var content = document.createElement('div'); - content.setAttribute('hidden', true); - var title = document.createElement('h1'); - var text = document.createElement('p'); - content.style.left = Math.floor(rect[2]) + 'px'; - content.style.top = Math.floor(rect[1]) + 'px'; - title.textContent = item.title; - - if (!item.content && !item.title) { - content.setAttribute('hidden', true); - } else { - var e = document.createElement('span'); - var lines = item.content.split(/(?:\r\n?|\n)/); - for (var i = 0, ii = lines.length; i < ii; ++i) { - var line = lines[i]; - e.appendChild(document.createTextNode(line)); - if (i < (ii - 1)) - e.appendChild(document.createElement('br')); - } - text.appendChild(e); - image.addEventListener('mouseover', function annotationImageOver() { - content.removeAttribute('hidden'); - }, false); - - image.addEventListener('mouseout', function annotationImageOut() { - content.setAttribute('hidden', true); - }, false); - } - - content.appendChild(title); - content.appendChild(text); - container.appendChild(image); - container.appendChild(content); - - return container; - } - - pdfPage.getAnnotations().then(function(items) { - for (var i = 0; i < items.length; i++) { - var item = items[i]; - switch (item.type) { - case 'Link': - var link = createElementWithStyle('a', item); - link.href = item.url || ''; - if (!item.url) - bindLink(link, ('dest' in item) ? item.dest : null); - div.appendChild(link); - break; - case 'Text': - var textAnnotation = createTextAnnotation(item); - if (textAnnotation) - div.appendChild(textAnnotation); - break; - } - } - }); - } - - this.getPagePoint = function pageViewGetPagePoint(x, y) { - return this.viewport.convertToPdfPoint(x, y); - }; - - this.scrollIntoView = function pageViewScrollIntoView(dest) { - if (!dest) { - scrollIntoView(div); - return; - } - - var x = 0, y = 0; - var width = 0, height = 0, widthScale, heightScale; - var scale = 0; - switch (dest[1].name) { - case 'XYZ': - x = dest[2]; - y = dest[3]; - scale = dest[4]; - // If x and/or y coordinates are not supplied, default to - // _top_ left of the page (not the obvious bottom left, - // since aligning the bottom of the intended page with the - // top of the window is rarely helpful). - x = x !== null ? x : 0; - y = y !== null ? y : this.height / this.scale; - break; - case 'Fit': - case 'FitB': - scale = 'page-fit'; - break; - case 'FitH': - case 'FitBH': - y = dest[2]; - scale = 'page-width'; - break; - case 'FitV': - case 'FitBV': - x = dest[2]; - scale = 'page-height'; - break; - case 'FitR': - x = dest[2]; - y = dest[3]; - width = dest[4] - x; - height = dest[5] - y; - widthScale = (this.container.clientWidth - SCROLLBAR_PADDING) / - width / CSS_UNITS; - heightScale = (this.container.clientHeight - SCROLLBAR_PADDING) / - height / CSS_UNITS; - scale = Math.min(widthScale, heightScale); - break; - default: - return; - } - - if (scale && scale !== PDFView.currentScale) - PDFView.parseScale(scale, true, true); - else if (PDFView.currentScale === UNKNOWN_SCALE) - PDFView.parseScale(DEFAULT_SCALE, true, true); - - var boundingRect = [ - this.viewport.convertToViewportPoint(x, y), - this.viewport.convertToViewportPoint(x + width, y + height) - ]; - setTimeout(function pageViewScrollIntoViewRelayout() { - // letting page to re-layout before scrolling - var scale = PDFView.currentScale; - var x = Math.min(boundingRect[0][0], boundingRect[1][0]); - var y = Math.min(boundingRect[0][1], boundingRect[1][1]); - var width = Math.abs(boundingRect[0][0] - boundingRect[1][0]); - var height = Math.abs(boundingRect[0][1] - boundingRect[1][1]); - - scrollIntoView(div, {left: x, top: y, width: width, height: height}); - }, 0); - }; - - this.getTextContent = function pageviewGetTextContent() { - if (!this.textContent) { - this.textContent = this.pdfPage.getTextContent(); - } - return this.textContent; - }; - - this.draw = function pageviewDraw(callback) { - var pdfPage = this.pdfPage; - - if (!pdfPage) { - var promise = PDFView.getPage(this.id); - promise.then(function(pdfPage) { - this.setPdfPage(pdfPage); - this.draw(callback); - }.bind(this)); - return; - } - - if (this.renderingState !== RenderingStates.INITIAL) { - console.error('Must be in new state before drawing'); - } - - this.renderingState = RenderingStates.RUNNING; - - var canvas = document.createElement('canvas'); - canvas.id = 'page' + this.id; - div.appendChild(canvas); - this.canvas = canvas; - - var scale = this.scale, viewport = this.viewport; - var outputScale = PDFView.getOutputScale(); - canvas.width = Math.floor(viewport.width) * outputScale.sx; - canvas.height = Math.floor(viewport.height) * outputScale.sy; - - var textLayerDiv = null; - if (!PDFJS.disableTextLayer) { - textLayerDiv = document.createElement('div'); - textLayerDiv.className = 'textLayer'; - textLayerDiv.style.width = canvas.width + 'px'; - textLayerDiv.style.height = canvas.height + 'px'; - div.appendChild(textLayerDiv); - } - var textLayer = this.textLayer = - textLayerDiv ? new TextLayerBuilder(textLayerDiv, this.id - 1) : null; - - if (outputScale.scaled) { - var cssScale = 'scale(' + (1 / outputScale.sx) + ', ' + - (1 / outputScale.sy) + ')'; - CustomStyle.setProp('transform' , canvas, cssScale); - CustomStyle.setProp('transformOrigin' , canvas, '0% 0%'); - if (textLayerDiv) { - CustomStyle.setProp('transform' , textLayerDiv, cssScale); - CustomStyle.setProp('transformOrigin' , textLayerDiv, '0% 0%'); - } - } - - var ctx = canvas.getContext('2d'); - ctx.clearRect(0, 0, canvas.width, canvas.height); - // TODO(mack): use data attributes to store these - ctx._scaleX = outputScale.sx; - ctx._scaleY = outputScale.sy; - if (outputScale.scaled) { - ctx.scale(outputScale.sx, outputScale.sy); - } -//#if (FIREFOX || MOZCENTRAL) -// // Checking if document fonts are used only once -// var checkIfDocumentFontsUsed = !PDFView.pdfDocument.embeddedFontsUsed; -//#endif - - // Rendering area - - var self = this; - var renderingWasReset = false; - function pageViewDrawCallback(error) { - if (renderingWasReset) { - return; - } - - self.renderingState = RenderingStates.FINISHED; - - if (self.loadingIconDiv) { - div.removeChild(self.loadingIconDiv); - delete self.loadingIconDiv; - } - -//#if (FIREFOX || MOZCENTRAL) -// if (checkIfDocumentFontsUsed && PDFView.pdfDocument.embeddedFontsUsed && -// !PDFView.supportsDocumentFonts) { -// console.error(mozL10n.get('web_fonts_disabled', null, -// 'Web fonts are disabled: unable to use embedded PDF fonts.')); -// PDFView.fallback(); -// } -//#endif - if (error) { - PDFView.error(mozL10n.get('rendering_error', null, - 'An error occurred while rendering the page.'), error); - } - - self.stats = pdfPage.stats; - self.updateStats(); - if (self.onAfterDraw) - self.onAfterDraw(); - - cache.push(self); - - var event = document.createEvent('CustomEvent'); - event.initCustomEvent('pagerender', true, true, { - pageNumber: pdfPage.pageNumber - }); - div.dispatchEvent(event); - - callback(); - } - - var renderContext = { - canvasContext: ctx, - viewport: this.viewport, - textLayer: textLayer, - continueCallback: function pdfViewcContinueCallback(cont) { - if (self.renderingState === RenderingStates.INITIAL) { - // The page update() was called, we just need to abort any rendering. - renderingWasReset = true; - return; - } - - if (PDFView.highestPriorityPage !== 'page' + self.id) { - self.renderingState = RenderingStates.PAUSED; - self.resume = function resumeCallback() { - self.renderingState = RenderingStates.RUNNING; - cont(); - }; - return; - } - cont(); - } - }; - this.pdfPage.render(renderContext).then( - function pdfPageRenderCallback() { - pageViewDrawCallback(null); - }, - function pdfPageRenderError(error) { - pageViewDrawCallback(error); - } - ); - - if (textLayer) { - this.getTextContent().then( - function textContentResolved(textContent) { - textLayer.setTextContent(textContent); - } - ); - } - - setupAnnotations(this.pdfPage, this.viewport); - div.setAttribute('data-loaded', true); - }; - - this.beforePrint = function pageViewBeforePrint() { - var pdfPage = this.pdfPage; - - var viewport = pdfPage.getViewport(1); - // Use the same hack we use for high dpi displays for printing to get better - // output until bug 811002 is fixed in FF. - var PRINT_OUTPUT_SCALE = 2; - var canvas = this.canvas = document.createElement('canvas'); - canvas.width = Math.floor(viewport.width) * PRINT_OUTPUT_SCALE; - canvas.height = Math.floor(viewport.height) * PRINT_OUTPUT_SCALE; - canvas.style.width = (PRINT_OUTPUT_SCALE * viewport.width) + 'pt'; - canvas.style.height = (PRINT_OUTPUT_SCALE * viewport.height) + 'pt'; - var cssScale = 'scale(' + (1 / PRINT_OUTPUT_SCALE) + ', ' + - (1 / PRINT_OUTPUT_SCALE) + ')'; - CustomStyle.setProp('transform' , canvas, cssScale); - CustomStyle.setProp('transformOrigin' , canvas, '0% 0%'); - - var printContainer = document.getElementById('printContainer'); - printContainer.appendChild(canvas); - - var self = this; - canvas.mozPrintCallback = function(obj) { - var ctx = obj.context; - - ctx.save(); - ctx.fillStyle = 'rgb(255, 255, 255)'; - ctx.fillRect(0, 0, canvas.width, canvas.height); - ctx.restore(); - ctx.scale(PRINT_OUTPUT_SCALE, PRINT_OUTPUT_SCALE); - - var renderContext = { - canvasContext: ctx, - viewport: viewport - }; - - pdfPage.render(renderContext).then(function() { - // Tell the printEngine that rendering this canvas/page has finished. - obj.done(); - self.pdfPage.destroy(); - }, function(error) { - console.error(error); - // Tell the printEngine that rendering this canvas/page has failed. - // This will make the print proces stop. - if ('abort' in obj) - obj.abort(); - else - obj.done(); - self.pdfPage.destroy(); - }); - }; - }; - - this.updateStats = function pageViewUpdateStats() { - if (!this.stats) { - return; - } - - if (PDFJS.pdfBug && Stats.enabled) { - var stats = this.stats; - Stats.add(this.id, stats); - } - }; -}; - -var ThumbnailView = function thumbnailView(container, id, defaultViewport) { - var anchor = document.createElement('a'); - anchor.href = PDFView.getAnchorUrl('#page=' + id); - anchor.title = mozL10n.get('thumb_page_title', {page: id}, 'Page {{page}}'); - anchor.onclick = function stopNavigation() { - PDFView.page = id; - return false; - }; - - - this.pdfPage = undefined; - this.viewport = defaultViewport; - this.pdfPageRotate = defaultViewport.rotate; - - this.rotation = 0; - this.pageWidth = this.viewport.width; - this.pageHeight = this.viewport.height; - this.pageRatio = this.pageWidth / this.pageHeight; - this.id = id; - - this.canvasWidth = 98; - this.canvasHeight = this.canvasWidth / this.pageWidth * this.pageHeight; - this.scale = (this.canvasWidth / this.pageWidth); - - var div = this.el = document.createElement('div'); - div.id = 'thumbnailContainer' + id; - div.className = 'thumbnail'; - - if (id === 1) { - // Highlight the thumbnail of the first page when no page number is - // specified (or exists in cache) when the document is loaded. - div.classList.add('selected'); - } - - var ring = document.createElement('div'); - ring.className = 'thumbnailSelectionRing'; - ring.style.width = this.canvasWidth + 'px'; - ring.style.height = this.canvasHeight + 'px'; - - div.appendChild(ring); - anchor.appendChild(div); - container.appendChild(anchor); - - this.hasImage = false; - this.renderingState = RenderingStates.INITIAL; - - this.setPdfPage = function thumbnailViewSetPdfPage(pdfPage) { - this.pdfPage = pdfPage; - this.pdfPageRotate = pdfPage.rotate; - this.viewport = pdfPage.getViewport(1); - this.update(); - }; - - this.update = function thumbnailViewUpdate(rot) { - if (!this.pdfPage) { - return; - } - - if (rot !== undefined) { - this.rotation = rot; - } - - var totalRotation = (this.rotation + this.pdfPage.rotate) % 360; - this.viewport = this.viewport.clone({ - scale: 1, - rotation: totalRotation - }); - this.pageWidth = this.viewport.width; - this.pageHeight = this.viewport.height; - this.pageRatio = this.pageWidth / this.pageHeight; - - this.canvasHeight = this.canvasWidth / this.pageWidth * this.pageHeight; - this.scale = (this.canvasWidth / this.pageWidth); - - div.removeAttribute('data-loaded'); - ring.textContent = ''; - ring.style.width = this.canvasWidth + 'px'; - ring.style.height = this.canvasHeight + 'px'; - - this.hasImage = false; - this.renderingState = RenderingStates.INITIAL; - this.resume = null; - }; - - this.getPageDrawContext = function thumbnailViewGetPageDrawContext() { - var canvas = document.createElement('canvas'); - canvas.id = 'thumbnail' + id; - - canvas.width = this.canvasWidth; - canvas.height = this.canvasHeight; - canvas.className = 'thumbnailImage'; - canvas.setAttribute('aria-label', mozL10n.get('thumb_page_canvas', - {page: id}, 'Thumbnail of Page {{page}}')); - - div.setAttribute('data-loaded', true); - - ring.appendChild(canvas); - - var ctx = canvas.getContext('2d'); - ctx.save(); - ctx.fillStyle = 'rgb(255, 255, 255)'; - ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight); - ctx.restore(); - return ctx; - }; - - this.drawingRequired = function thumbnailViewDrawingRequired() { - return !this.hasImage; - }; - - this.draw = function thumbnailViewDraw(callback) { - if (!this.pdfPage) { - var promise = PDFView.getPage(this.id); - promise.then(function(pdfPage) { - this.setPdfPage(pdfPage); - this.draw(callback); - }.bind(this)); - return; - } - - if (this.renderingState !== RenderingStates.INITIAL) { - console.error('Must be in new state before drawing'); - } - - this.renderingState = RenderingStates.RUNNING; - if (this.hasImage) { - callback(); - return; - } - - var self = this; - var ctx = this.getPageDrawContext(); - var drawViewport = this.viewport.clone({ scale: this.scale }); - var renderContext = { - canvasContext: ctx, - viewport: drawViewport, - continueCallback: function(cont) { - if (PDFView.highestPriorityPage !== 'thumbnail' + self.id) { - self.renderingState = RenderingStates.PAUSED; - self.resume = function() { - self.renderingState = RenderingStates.RUNNING; - cont(); - }; - return; - } - cont(); - } - }; - this.pdfPage.render(renderContext).then( - function pdfPageRenderCallback() { - self.renderingState = RenderingStates.FINISHED; - callback(); - }, - function pdfPageRenderError(error) { - self.renderingState = RenderingStates.FINISHED; - callback(); - } - ); - this.hasImage = true; - }; - - this.setImage = function thumbnailViewSetImage(img) { - if (this.hasImage || !img) - return; - this.renderingState = RenderingStates.FINISHED; - var ctx = this.getPageDrawContext(); - ctx.drawImage(img, 0, 0, img.width, img.height, - 0, 0, ctx.canvas.width, ctx.canvas.height); - - this.hasImage = true; - }; -}; - -var DocumentOutlineView = function documentOutlineView(outline) { - var outlineView = document.getElementById('outlineView'); - while (outlineView.firstChild) - outlineView.removeChild(outlineView.firstChild); - - function bindItemLink(domObj, item) { - domObj.href = PDFView.getDestinationHash(item.dest); - domObj.onclick = function documentOutlineViewOnclick(e) { - PDFView.navigateTo(item.dest); - return false; - }; - } - - if (!outline) { - var noOutline = document.createElement('div'); - noOutline.classList.add('noOutline'); - noOutline.textContent = mozL10n.get('no_outline', null, - 'No Outline Available'); - outlineView.appendChild(noOutline); - return; - } - - var queue = [{parent: outlineView, items: outline}]; - while (queue.length > 0) { - var levelData = queue.shift(); - var i, n = levelData.items.length; - for (i = 0; i < n; i++) { - var item = levelData.items[i]; - var div = document.createElement('div'); - div.className = 'outlineItem'; - var a = document.createElement('a'); - bindItemLink(a, item); - a.textContent = item.title; - div.appendChild(a); - - if (item.items.length > 0) { - var itemsDiv = document.createElement('div'); - itemsDiv.className = 'outlineItems'; - div.appendChild(itemsDiv); - queue.push({parent: itemsDiv, items: item.items}); - } - - levelData.parent.appendChild(div); - } - } -}; - -// optimised CSS custom property getter/setter -var CustomStyle = (function CustomStyleClosure() { - - // As noted on: http://www.zachstronaut.com/posts/2009/02/17/ - // animate-css-transforms-firefox-webkit.html - // in some versions of IE9 it is critical that ms appear in this list - // before Moz - var prefixes = ['ms', 'Moz', 'Webkit', 'O']; - var _cache = { }; - - function CustomStyle() { - } - - CustomStyle.getProp = function get(propName, element) { - // check cache only when no element is given - if (arguments.length == 1 && typeof _cache[propName] == 'string') { - return _cache[propName]; - } - - element = element || document.documentElement; - var style = element.style, prefixed, uPropName; - - // test standard property first - if (typeof style[propName] == 'string') { - return (_cache[propName] = propName); - } - - // capitalize - uPropName = propName.charAt(0).toUpperCase() + propName.slice(1); - - // test vendor specific properties - for (var i = 0, l = prefixes.length; i < l; i++) { - prefixed = prefixes[i] + uPropName; - if (typeof style[prefixed] == 'string') { - return (_cache[propName] = prefixed); - } - } - - //if all fails then set to undefined - return (_cache[propName] = 'undefined'); - }; - - CustomStyle.setProp = function set(propName, element, str) { - var prop = this.getProp(propName); - if (prop != 'undefined') - element.style[prop] = str; - }; - - return CustomStyle; -})(); - -var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { - var textLayerFrag = document.createDocumentFragment(); - - this.textLayerDiv = textLayerDiv; - this.layoutDone = false; - this.divContentDone = false; - this.pageIdx = pageIdx; - this.matches = []; - - this.beginLayout = function textLayerBuilderBeginLayout() { - this.textDivs = []; - this.textLayerQueue = []; - this.renderingDone = false; - }; - - this.endLayout = function textLayerBuilderEndLayout() { - this.layoutDone = true; - this.insertDivContent(); - }; - - this.renderLayer = function textLayerBuilderRenderLayer() { - var self = this; - var textDivs = this.textDivs; - var bidiTexts = this.textContent.bidiTexts; - var textLayerDiv = this.textLayerDiv; - var canvas = document.createElement('canvas'); - var ctx = canvas.getContext('2d'); - - // No point in rendering so many divs as it'd make the browser unusable - // even after the divs are rendered - var MAX_TEXT_DIVS_TO_RENDER = 100000; - if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER) - return; - - for (var i = 0, ii = textDivs.length; i < ii; i++) { - var textDiv = textDivs[i]; - if ('isWhitespace' in textDiv.dataset) { - continue; - } - textLayerFrag.appendChild(textDiv); - - ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily; - var width = ctx.measureText(textDiv.textContent).width; - - if (width > 0) { - var textScale = textDiv.dataset.canvasWidth / width; - - var transform = 'scale(' + textScale + ', 1)'; - if (bidiTexts[i].dir === 'ttb') { - transform = 'rotate(90deg) ' + transform; - } - CustomStyle.setProp('transform' , textDiv, transform); - CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%'); - - textLayerDiv.appendChild(textDiv); - } - } - - this.renderingDone = true; - this.updateMatches(); - - textLayerDiv.appendChild(textLayerFrag); - }; - - this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() { - // Schedule renderLayout() if user has been scrolling, otherwise - // run it right away - var RENDER_DELAY = 200; // in ms - var self = this; - if (Date.now() - PDFView.lastScroll > RENDER_DELAY) { - // Render right away - this.renderLayer(); - } else { - // Schedule - if (this.renderTimer) - clearTimeout(this.renderTimer); - this.renderTimer = setTimeout(function() { - self.setupRenderLayoutTimer(); - }, RENDER_DELAY); - } - }; - - this.appendText = function textLayerBuilderAppendText(geom) { - var textDiv = document.createElement('div'); - - // vScale and hScale already contain the scaling to pixel units - var fontHeight = geom.fontSize * Math.abs(geom.vScale); - textDiv.dataset.canvasWidth = geom.canvasWidth * geom.hScale; - textDiv.dataset.fontName = geom.fontName; - - textDiv.style.fontSize = fontHeight + 'px'; - textDiv.style.fontFamily = geom.fontFamily; - textDiv.style.left = geom.x + 'px'; - textDiv.style.top = (geom.y - fontHeight) + 'px'; - - // The content of the div is set in the `setTextContent` function. - - this.textDivs.push(textDiv); - }; - - this.insertDivContent = function textLayerUpdateTextContent() { - // Only set the content of the divs once layout has finished, the content - // for the divs is available and content is not yet set on the divs. - if (!this.layoutDone || this.divContentDone || !this.textContent) - return; - - this.divContentDone = true; - - var textDivs = this.textDivs; - var bidiTexts = this.textContent.bidiTexts; - - for (var i = 0; i < bidiTexts.length; i++) { - var bidiText = bidiTexts[i]; - var textDiv = textDivs[i]; - if (!/\S/.test(bidiText.str)) { - textDiv.dataset.isWhitespace = true; - continue; - } - - textDiv.textContent = bidiText.str; - // bidiText.dir may be 'ttb' for vertical texts. - textDiv.dir = bidiText.dir === 'rtl' ? 'rtl' : 'ltr'; - } - - this.setupRenderLayoutTimer(); - }; - - this.setTextContent = function textLayerBuilderSetTextContent(textContent) { - this.textContent = textContent; - this.insertDivContent(); - }; - - this.convertMatches = function textLayerBuilderConvertMatches(matches) { - var i = 0; - var iIndex = 0; - var bidiTexts = this.textContent.bidiTexts; - var end = bidiTexts.length - 1; - var queryLen = PDFFindController.state.query.length; - - var lastDivIdx = -1; - var pos; - - var ret = []; - - // Loop over all the matches. - for (var m = 0; m < matches.length; m++) { - var matchIdx = matches[m]; - // # Calculate the begin position. - - // Loop over the divIdxs. - while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) { - iIndex += bidiTexts[i].str.length; - i++; - } - - // TODO: Do proper handling here if something goes wrong. - if (i == bidiTexts.length) { - console.error('Could not find matching mapping'); - } - - var match = { - begin: { - divIdx: i, - offset: matchIdx - iIndex - } - }; - - // # Calculate the end position. - matchIdx += queryLen; - - // Somewhat same array as above, but use a > instead of >= to get the end - // position right. - while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) { - iIndex += bidiTexts[i].str.length; - i++; - } - - match.end = { - divIdx: i, - offset: matchIdx - iIndex - }; - ret.push(match); - } - - return ret; - }; - - this.renderMatches = function textLayerBuilder_renderMatches(matches) { - // Early exit if there is nothing to render. - if (matches.length === 0) { - return; - } - - var bidiTexts = this.textContent.bidiTexts; - var textDivs = this.textDivs; - var prevEnd = null; - var isSelectedPage = this.pageIdx === PDFFindController.selected.pageIdx; - var selectedMatchIdx = PDFFindController.selected.matchIdx; - var highlightAll = PDFFindController.state.highlightAll; - - var infty = { - divIdx: -1, - offset: undefined - }; - - function beginText(begin, className) { - var divIdx = begin.divIdx; - var div = textDivs[divIdx]; - div.textContent = ''; - - var content = bidiTexts[divIdx].str.substring(0, begin.offset); - var node = document.createTextNode(content); - if (className) { - var isSelected = isSelectedPage && - divIdx === selectedMatchIdx; - var span = document.createElement('span'); - span.className = className + (isSelected ? ' selected' : ''); - span.appendChild(node); - div.appendChild(span); - return; - } - div.appendChild(node); - } - - function appendText(from, to, className) { - var divIdx = from.divIdx; - var div = textDivs[divIdx]; - - var content = bidiTexts[divIdx].str.substring(from.offset, to.offset); - var node = document.createTextNode(content); - if (className) { - var span = document.createElement('span'); - span.className = className; - span.appendChild(node); - div.appendChild(span); - return; - } - div.appendChild(node); - } - - function highlightDiv(divIdx, className) { - textDivs[divIdx].className = className; - } - - var i0 = selectedMatchIdx, i1 = i0 + 1, i; - - if (highlightAll) { - i0 = 0; - i1 = matches.length; - } else if (!isSelectedPage) { - // Not highlighting all and this isn't the selected page, so do nothing. - return; - } - - for (i = i0; i < i1; i++) { - var match = matches[i]; - var begin = match.begin; - var end = match.end; - - var isSelected = isSelectedPage && i === selectedMatchIdx; - var highlightSuffix = (isSelected ? ' selected' : ''); - if (isSelected) - scrollIntoView(textDivs[begin.divIdx], {top: -50}); - - // Match inside new div. - if (!prevEnd || begin.divIdx !== prevEnd.divIdx) { - // If there was a previous div, then add the text at the end - if (prevEnd !== null) { - appendText(prevEnd, infty); - } - // clears the divs and set the content until the begin point. - beginText(begin); - } else { - appendText(prevEnd, begin); - } - - if (begin.divIdx === end.divIdx) { - appendText(begin, end, 'highlight' + highlightSuffix); - } else { - appendText(begin, infty, 'highlight begin' + highlightSuffix); - for (var n = begin.divIdx + 1; n < end.divIdx; n++) { - highlightDiv(n, 'highlight middle' + highlightSuffix); - } - beginText(end, 'highlight end' + highlightSuffix); - } - prevEnd = end; - } - - if (prevEnd) { - appendText(prevEnd, infty); - } - }; - - this.updateMatches = function textLayerUpdateMatches() { - // Only show matches, once all rendering is done. - if (!this.renderingDone) - return; - - // Clear out all matches. - var matches = this.matches; - var textDivs = this.textDivs; - var bidiTexts = this.textContent.bidiTexts; - var clearedUntilDivIdx = -1; - - // Clear out all current matches. - for (var i = 0; i < matches.length; i++) { - var match = matches[i]; - var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx); - for (var n = begin; n <= match.end.divIdx; n++) { - var div = textDivs[n]; - div.textContent = bidiTexts[n].str; - div.className = ''; - } - clearedUntilDivIdx = match.end.divIdx + 1; - } - - if (!PDFFindController.active) - return; - - // Convert the matches on the page controller into the match format used - // for the textLayer. - this.matches = matches = - this.convertMatches(PDFFindController.pageMatches[this.pageIdx] || []); - - this.renderMatches(this.matches); - }; -}; - -document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) { - PDFView.initialize(); - var params = PDFView.parseQueryString(document.location.search.substring(1)); - -//#if !(FIREFOX || MOZCENTRAL) - var file = params.file || DEFAULT_URL; -//#else -//var file = window.location.toString() -//#endif - -//#if !(FIREFOX || MOZCENTRAL) - if (!window.File || !window.FileReader || !window.FileList || !window.Blob) { - document.getElementById('openFile').setAttribute('hidden', 'true'); - } else { - document.getElementById('fileInput').value = null; - } -//#else -//document.getElementById('openFile').setAttribute('hidden', 'true'); -//#endif - - // Special debugging flags in the hash section of the URL. - var hash = document.location.hash.substring(1); - var hashParams = PDFView.parseQueryString(hash); - - if ('disableWorker' in hashParams) - PDFJS.disableWorker = (hashParams['disableWorker'] === 'true'); - -//#if !(FIREFOX || MOZCENTRAL) - var locale = navigator.language; - if ('locale' in hashParams) - locale = hashParams['locale']; - mozL10n.setLanguage(locale); -//#endif - - if ('textLayer' in hashParams) { - switch (hashParams['textLayer']) { - case 'off': - PDFJS.disableTextLayer = true; - break; - case 'visible': - case 'shadow': - case 'hover': - var viewer = document.getElementById('viewer'); - viewer.classList.add('textLayer-' + hashParams['textLayer']); - break; - } - } - -//#if !(FIREFOX || MOZCENTRAL) - if ('pdfBug' in hashParams) { -//#else -//if ('pdfBug' in hashParams && FirefoxCom.requestSync('pdfBugEnabled')) { -//#endif - PDFJS.pdfBug = true; - var pdfBug = hashParams['pdfBug']; - var enabled = pdfBug.split(','); - PDFBug.enable(enabled); - PDFBug.init(); - } - - if (!PDFView.supportsPrinting) { - document.getElementById('print').classList.add('hidden'); - } - - if (!PDFView.supportsFullscreen) { - document.getElementById('fullscreen').classList.add('hidden'); - } - - if (PDFView.supportsIntegratedFind) { - document.querySelector('#viewFind').classList.add('hidden'); - } - - // Listen for warnings to trigger the fallback UI. Errors should be caught - // and call PDFView.error() so we don't need to listen for those. - PDFJS.LogManager.addLogger({ - warn: function() { - PDFView.fallback(); - } - }); - - var mainContainer = document.getElementById('mainContainer'); - var outerContainer = document.getElementById('outerContainer'); - mainContainer.addEventListener('transitionend', function(e) { - if (e.target == mainContainer) { - var event = document.createEvent('UIEvents'); - event.initUIEvent('resize', false, false, window, 0); - window.dispatchEvent(event); - outerContainer.classList.remove('sidebarMoving'); - } - }, true); - - document.getElementById('sidebarToggle').addEventListener('click', - function() { - this.classList.toggle('toggled'); - outerContainer.classList.add('sidebarMoving'); - outerContainer.classList.toggle('sidebarOpen'); - PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen'); - PDFView.renderHighestPriority(); - }); - - document.getElementById('viewThumbnail').addEventListener('click', - function() { - PDFView.switchSidebarView('thumbs'); - }); - - document.getElementById('viewOutline').addEventListener('click', - function() { - PDFView.switchSidebarView('outline'); - }); - - document.getElementById('previous').addEventListener('click', - function() { - PDFView.page--; - }); - - document.getElementById('next').addEventListener('click', - function() { - PDFView.page++; - }); - - document.querySelector('.zoomIn').addEventListener('click', - function() { - PDFView.zoomIn(); - }); - - document.querySelector('.zoomOut').addEventListener('click', - function() { - PDFView.zoomOut(); - }); - - document.getElementById('fullscreen').addEventListener('click', - function() { - PDFView.fullscreen(); - }); - - document.getElementById('openFile').addEventListener('click', - function() { - document.getElementById('fileInput').click(); - }); - - document.getElementById('print').addEventListener('click', - function() { - window.print(); - }); - - document.getElementById('download').addEventListener('click', - function() { - PDFView.download(); - }); - - document.getElementById('pageNumber').addEventListener('click', - function() { - this.select(); - }); - - document.getElementById('pageNumber').addEventListener('change', - function() { - // Handle the user inputting a floating point number. - PDFView.page = (this.value | 0); - - if (this.value !== (this.value | 0).toString()) { - this.value = PDFView.page; - } - }); - - document.getElementById('scaleSelect').addEventListener('change', - function() { - PDFView.parseScale(this.value); - }); - - document.getElementById('first_page').addEventListener('click', - function() { - PDFView.page = 1; - }); - - document.getElementById('last_page').addEventListener('click', - function() { - PDFView.page = PDFView.pdfDocument.numPages; - }); - - document.getElementById('page_rotate_ccw').addEventListener('click', - function() { - PDFView.rotatePages(-90); - }); - - document.getElementById('page_rotate_cw').addEventListener('click', - function() { - PDFView.rotatePages(90); - }); - -//#if (FIREFOX || MOZCENTRAL) -//if (FirefoxCom.requestSync('getLoadingType') == 'passive') { -// PDFView.setTitleUsingUrl(file); -// PDFView.initPassiveLoading(); -// return; -//} -//#endif - -//#if !B2G - PDFView.open(file, 0); -//#endif -}, true); - -function updateViewarea() { - - if (!PDFView.initialized) - return; - var visible = PDFView.getVisiblePages(); - var visiblePages = visible.views; - if (visiblePages.length === 0) { - return; - } - - PDFView.renderHighestPriority(); - - var currentId = PDFView.page; - var firstPage = visible.first; - - for (var i = 0, ii = visiblePages.length, stillFullyVisible = false; - i < ii; ++i) { - var page = visiblePages[i]; - - if (page.percent < 100) - break; - - if (page.id === PDFView.page) { - stillFullyVisible = true; - break; - } - } - - if (!stillFullyVisible) { - currentId = visiblePages[0].id; - } - - if (!PDFView.isFullscreen) { - updateViewarea.inProgress = true; // used in "set page" - PDFView.page = currentId; - updateViewarea.inProgress = false; - } - - var currentScale = PDFView.currentScale; - var currentScaleValue = PDFView.currentScaleValue; - var normalizedScaleValue = currentScaleValue == currentScale ? - currentScale * 100 : currentScaleValue; - - var pageNumber = firstPage.id; - var pdfOpenParams = '#page=' + pageNumber; - pdfOpenParams += '&zoom=' + normalizedScaleValue; - var currentPage = PDFView.pages[pageNumber - 1]; - var topLeft = currentPage.getPagePoint(PDFView.container.scrollLeft, - (PDFView.container.scrollTop - firstPage.y)); - pdfOpenParams += ',' + Math.round(topLeft[0]) + ',' + Math.round(topLeft[1]); - - var store = PDFView.store; - store.initializedPromise.then(function() { - store.set('exists', true); - store.set('page', pageNumber); - store.set('zoom', normalizedScaleValue); - store.set('scrollLeft', Math.round(topLeft[0])); - store.set('scrollTop', Math.round(topLeft[1])); - }); - var href = PDFView.getAnchorUrl(pdfOpenParams); - document.getElementById('viewBookmark').href = href; -} - -window.addEventListener('resize', function webViewerResize(evt) { - if (PDFView.initialized && - (document.getElementById('pageWidthOption').selected || - document.getElementById('pageFitOption').selected || - document.getElementById('pageAutoOption').selected)) - PDFView.parseScale(document.getElementById('scaleSelect').value); - updateViewarea(); -}); - -window.addEventListener('hashchange', function webViewerHashchange(evt) { - PDFView.setHash(document.location.hash.substring(1)); -}); - -window.addEventListener('change', function webViewerChange(evt) { - var files = evt.target.files; - if (!files || files.length === 0) - return; - - // Read the local file into a Uint8Array. - var fileReader = new FileReader(); - fileReader.onload = function webViewerChangeFileReaderOnload(evt) { - var buffer = evt.target.result; - var uint8Array = new Uint8Array(buffer); - PDFView.open(uint8Array, 0); - }; - - var file = files[0]; - fileReader.readAsArrayBuffer(file); - PDFView.setTitleUsingUrl(file.name); - - // URL does not reflect proper document location - hiding some icons. - document.getElementById('viewBookmark').setAttribute('hidden', 'true'); - document.getElementById('download').setAttribute('hidden', 'true'); -}, true); - -function selectScaleOption(value) { - var options = document.getElementById('scaleSelect').options; - var predefinedValueFound = false; - for (var i = 0; i < options.length; i++) { - var option = options[i]; - if (option.value != value) { - option.selected = false; - continue; - } - option.selected = true; - predefinedValueFound = true; - } - return predefinedValueFound; -} - -window.addEventListener('localized', function localized(evt) { - document.getElementsByTagName('html')[0].dir = mozL10n.getDirection(); - - // Adjust the width of the zoom box to fit the content. - PDFView.animationStartedPromise.then( - function() { - var container = document.getElementById('scaleSelectContainer'); - var select = document.getElementById('scaleSelect'); - select.setAttribute('style', 'min-width: inherit;'); - var width = select.clientWidth + 8; - select.setAttribute('style', 'min-width: ' + (width + 20) + 'px;'); - container.setAttribute('style', 'min-width: ' + width + 'px; ' + - 'max-width: ' + width + 'px;'); - }); -}, true); - -window.addEventListener('scalechange', function scalechange(evt) { - var customScaleOption = document.getElementById('customScaleOption'); - customScaleOption.selected = false; - - if (!evt.resetAutoSettings && - (document.getElementById('pageWidthOption').selected || - document.getElementById('pageFitOption').selected || - document.getElementById('pageAutoOption').selected)) { - updateViewarea(); - return; - } - - var predefinedValueFound = selectScaleOption('' + evt.scale); - if (!predefinedValueFound) { - customScaleOption.textContent = Math.round(evt.scale * 10000) / 100 + '%'; - customScaleOption.selected = true; - } - - document.getElementById('zoom_out').disabled = (evt.scale === MIN_SCALE); - document.getElementById('zoom_in').disabled = (evt.scale === MAX_SCALE); - - updateViewarea(); -}, true); - -window.addEventListener('pagechange', function pagechange(evt) { - var page = evt.pageNumber; - if (PDFView.previousPageNumber !== page) { - document.getElementById('pageNumber').value = page; - var selected = document.querySelector('.thumbnail.selected'); - if (selected) - selected.classList.remove('selected'); - var thumbnail = document.getElementById('thumbnailContainer' + page); - thumbnail.classList.add('selected'); - var visibleThumbs = PDFView.getVisibleThumbs(); - var numVisibleThumbs = visibleThumbs.views.length; - // If the thumbnail isn't currently visible scroll it into view. - if (numVisibleThumbs > 0) { - var first = visibleThumbs.first.id; - // Account for only one thumbnail being visible. - var last = numVisibleThumbs > 1 ? - visibleThumbs.last.id : first; - if (page <= first || page >= last) - scrollIntoView(thumbnail); - } - - } - document.getElementById('previous').disabled = (page <= 1); - document.getElementById('next').disabled = (page >= PDFView.pages.length); -}, true); - -// Firefox specific event, so that we can prevent browser from zooming -window.addEventListener('DOMMouseScroll', function(evt) { - if (evt.ctrlKey) { - evt.preventDefault(); - - var ticks = evt.detail; - var direction = (ticks > 0) ? 'zoomOut' : 'zoomIn'; - for (var i = 0, length = Math.abs(ticks); i < length; i++) - PDFView[direction](); - } else if (PDFView.isFullscreen) { - var FIREFOX_DELTA_FACTOR = -40; - PDFView.mouseScroll(evt.detail * FIREFOX_DELTA_FACTOR); - } -}, false); - -window.addEventListener('mousemove', function mousemove(evt) { - if (PDFView.isFullscreen) { - PDFView.showPresentationControls(); - } -}, false); - -window.addEventListener('mousedown', function mousedown(evt) { - if (PDFView.isFullscreen && evt.button === 0) { - // Enable clicking of links in fullscreen mode. - // Note: Only links that point to the currently loaded PDF document works. - var targetHref = evt.target.href; - var internalLink = targetHref && (targetHref.replace(/#.*$/, '') === - window.location.href.replace(/#.*$/, '')); - if (!internalLink) { - // Unless an internal link was clicked, advance a page in fullscreen mode. - evt.preventDefault(); - PDFView.page++; - } - } -}, false); - -window.addEventListener('click', function click(evt) { - if (PDFView.isFullscreen && evt.button === 0) { - // Necessary since preventDefault() in 'mousedown' won't stop - // the event propagation in all circumstances. - evt.preventDefault(); - } -}, false); - -window.addEventListener('keydown', function keydown(evt) { - var handled = false; - var cmd = (evt.ctrlKey ? 1 : 0) | - (evt.altKey ? 2 : 0) | - (evt.shiftKey ? 4 : 0) | - (evt.metaKey ? 8 : 0); - - // First, handle the key bindings that are independent whether an input - // control is selected or not. - if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) { - // either CTRL or META key with optional SHIFT. - switch (evt.keyCode) { - case 70: - if (!PDFView.supportsIntegratedFind) { - PDFFindBar.toggle(); - handled = true; - } - break; - case 61: // FF/Mac '=' - case 107: // FF '+' and '=' - case 187: // Chrome '+' - case 171: // FF with German keyboard - PDFView.zoomIn(); - handled = true; - break; - case 173: // FF/Mac '-' - case 109: // FF '-' - case 189: // Chrome '-' - PDFView.zoomOut(); - handled = true; - break; - case 48: // '0' - case 96: // '0' on Numpad of Swedish keyboard - PDFView.parseScale(DEFAULT_SCALE, true); - handled = false; // keeping it unhandled (to restore page zoom to 100%) - break; - } - } - - // CTRL or META with or without SHIFT. - if (cmd == 1 || cmd == 8 || cmd == 5 || cmd == 12) { - switch (evt.keyCode) { - case 71: // g - if (!PDFView.supportsIntegratedFind) { - PDFFindBar.dispatchEvent('again', cmd == 5 || cmd == 12); - handled = true; - } - break; - } - } - - if (handled) { - evt.preventDefault(); - return; - } - - // Some shortcuts should not get handled if a control/input element - // is selected. - var curElement = document.activeElement; - if (curElement && (curElement.tagName == 'INPUT' || - curElement.tagName == 'SELECT')) { - return; - } - var controlsElement = document.getElementById('toolbar'); - while (curElement) { - if (curElement === controlsElement && !PDFView.isFullscreen) - return; // ignoring if the 'toolbar' element is focused - curElement = curElement.parentNode; - } - - if (cmd === 0) { // no control key pressed at all. - switch (evt.keyCode) { - case 38: // up arrow - case 33: // pg up - case 8: // backspace - if (!PDFView.isFullscreen && PDFView.currentScaleValue !== 'page-fit') { - break; - } - /* in fullscreen mode */ - /* falls through */ - case 37: // left arrow - // horizontal scrolling using arrow keys - if (PDFView.isHorizontalScrollbarEnabled) { - break; - } - /* falls through */ - case 75: // 'k' - case 80: // 'p' - PDFView.page--; - handled = true; - break; - case 27: // esc key - if (!PDFView.supportsIntegratedFind && PDFFindBar.opened) { - PDFFindBar.close(); - handled = true; - } - break; - case 40: // down arrow - case 34: // pg down - case 32: // spacebar - if (!PDFView.isFullscreen && PDFView.currentScaleValue !== 'page-fit') { - break; - } - /* falls through */ - case 39: // right arrow - // horizontal scrolling using arrow keys - if (PDFView.isHorizontalScrollbarEnabled) { - break; - } - /* falls through */ - case 74: // 'j' - case 78: // 'n' - PDFView.page++; - handled = true; - break; - - case 36: // home - if (PDFView.isFullscreen) { - PDFView.page = 1; - handled = true; - } - break; - case 35: // end - if (PDFView.isFullscreen) { - PDFView.page = PDFView.pdfDocument.numPages; - handled = true; - } - break; - - case 82: // 'r' - PDFView.rotatePages(90); - break; - } - } - - if (cmd == 4) { // shift-key - switch (evt.keyCode) { - case 82: // 'r' - PDFView.rotatePages(-90); - break; - } - } - - if (handled) { - evt.preventDefault(); - PDFView.clearMouseScrollState(); - } -}); - -window.addEventListener('beforeprint', function beforePrint(evt) { - PDFView.beforePrint(); -}); - -window.addEventListener('afterprint', function afterPrint(evt) { - PDFView.afterPrint(); -}); - -(function fullscreenClosure() { - function fullscreenChange(e) { - var isFullscreen = document.fullscreenElement || document.mozFullScreen || - document.webkitIsFullScreen; - - if (!isFullscreen) { - PDFView.exitFullscreen(); - } - } - - window.addEventListener('fullscreenchange', fullscreenChange, false); - window.addEventListener('mozfullscreenchange', fullscreenChange, false); - window.addEventListener('webkitfullscreenchange', fullscreenChange, false); -})(); - -(function animationStartedClosure() { - // The offsetParent is not set until the pdf.js iframe or object is visible. - // Waiting for first animation. - var requestAnimationFrame = window.requestAnimationFrame || - window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function startAtOnce(callback) { callback(); }; - PDFView.animationStartedPromise = new PDFJS.Promise(); - requestAnimationFrame(function onAnimationFrame() { - PDFView.animationStartedPromise.resolve(); - }); -})(); - -//#if B2G -//window.navigator.mozSetMessageHandler('activity', function(activity) { -// var url = activity.source.data.url; -// PDFView.open(url); -// var cancelButton = document.getElementById('activityClose'); -// cancelButton.addEventListener('click', function() { -// activity.postResult('close'); -// }); -//}); -//#endif diff --git a/mediagoblin/static/js/setup_report_forms.js b/mediagoblin/static/js/setup_report_forms.js new file mode 100644 index 00000000..a75a92dd --- /dev/null +++ b/mediagoblin/static/js/setup_report_forms.js @@ -0,0 +1,67 @@ +/** + * GNU MediaGoblin -- federated, autonomous media hosting + * Copyright (C) 2011, 2012 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/>. + */ + +function init_report_resolution_form() { + hidden_input_names = { + 'takeaway':['take_away_privileges'], + 'userban':['user_banned_until','why_user_was_banned'], + 'sendmessage':['message_to_user'] +} + init_user_banned_form(); + $('form#resolution_form').hide() + $('#open_resolution_form').click(function() { + $('form#resolution_form').toggle(); + $.each(hidden_input_names, function(key, list){ + $.each(list, function(index, name){ + $('label[for='+name+']').hide(); + $('#'+name).hide(); + }); + }); + }); + $('#action_to_resolve').change(function() { + $('ul#action_to_resolve li input:checked').each(function() { + $.each(hidden_input_names[$(this).val()], function(index, name){ + $('label[for='+name+']').show(); + $('#'+name).show(); + }); + }); + $('ul#action_to_resolve li input:not(:checked)').each(function() { + $.each(hidden_input_names[$(this).val()], function(index, name){ + $('label[for='+name+']').hide(); + $('#'+name).hide(); + }); + }); + }); + $("#submit_this_report").click(function(){ + submit_user_banned_form() + }); +} + +function submit_user_banned_form() { + if ($("#user_banned_until").val() == 'YYYY-MM-DD'){ + $("#user_banned_until").val(""); + } +} + +function init_user_banned_form() { + $('#user_banned_until').val("YYYY-MM-DD") + $("#user_banned_until").focus(function() { + $(this).val(""); + $(this).unbind('focus'); + }); +} diff --git a/mediagoblin/storage/__init__.py b/mediagoblin/storage/__init__.py index bbe134a7..51b46c07 100644 --- a/mediagoblin/storage/__init__.py +++ b/mediagoblin/storage/__init__.py @@ -191,6 +191,13 @@ class StorageInterface(object): # Copy to storage system in 4M chunks shutil.copyfileobj(source_file, dest_file, length=4*1048576) + def get_file_size(self, filepath): + """ + Return the size of the file in bytes. + """ + # Subclasses should override this method. + self.__raise_not_implemented() + ########### # Utilities diff --git a/mediagoblin/storage/cloudfiles.py b/mediagoblin/storage/cloudfiles.py index b6e57c91..47c81ad6 100644 --- a/mediagoblin/storage/cloudfiles.py +++ b/mediagoblin/storage/cloudfiles.py @@ -75,7 +75,7 @@ class CloudFilesStorage(StorageInterface): _log.debug('Container: {0}'.format( self.container.name)) - self.container_uri = self.container.public_uri() + self.container_uri = self.container.public_ssl_uri() def _resolve_filepath(self, filepath): return '/'.join( @@ -168,6 +168,12 @@ class CloudFilesStorage(StorageInterface): # Copy to storage system in 4096 byte chunks dest_file.send(source_file) + def get_file_size(self, filepath): + """Returns the file size in bytes""" + obj = self.container.get_object( + self._resolve_filepath(filepath)) + return obj.total_bytes + class CloudFilesStorageObjectWrapper(): """ Wrapper for python-cloudfiles's cloudfiles.storage_object.Object diff --git a/mediagoblin/storage/filestorage.py b/mediagoblin/storage/filestorage.py index 3d6e0753..29b8383b 100644 --- a/mediagoblin/storage/filestorage.py +++ b/mediagoblin/storage/filestorage.py @@ -111,3 +111,6 @@ class BasicFileStorage(StorageInterface): os.makedirs(directory) # This uses chunked copying of 16kb buffers (Py2.7): shutil.copy(filename, self.get_local_path(filepath)) + + def get_file_size(self, filepath): + return os.stat(self._resolve_filepath(filepath)).st_size diff --git a/mediagoblin/submit/forms.py b/mediagoblin/submit/forms.py index e9bd93fd..e2264645 100644 --- a/mediagoblin/submit/forms.py +++ b/mediagoblin/submit/forms.py @@ -17,30 +17,44 @@ import wtforms +from mediagoblin import mg_globals from mediagoblin.tools.text import tag_length_validator from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.tools.licenses import licenses_as_choices -class SubmitStartForm(wtforms.Form): - file = wtforms.FileField(_('File')) - title = wtforms.TextField( - _('Title'), - [wtforms.validators.Length(min=0, max=500)]) - description = wtforms.TextAreaField( - _('Description of this work'), - description=_("""You can use - <a href="http://daringfireball.net/projects/markdown/basics"> - Markdown</a> for formatting.""")) - tags = wtforms.TextField( - _('Tags'), - [tag_length_validator], - description=_( - "Separate tags by commas.")) - license = wtforms.SelectField( - _('License'), - [wtforms.validators.Optional(),], - choices=licenses_as_choices()) +def get_submit_start_form(form, **kwargs): + max_file_size = kwargs.get('max_file_size') + desc = None + if max_file_size: + desc = _('Max file size: {0} mb'.format(max_file_size)) + + class SubmitStartForm(wtforms.Form): + file = wtforms.FileField( + _('File'), + description=desc) + title = wtforms.TextField( + _('Title'), + [wtforms.validators.Length(min=0, max=500)]) + description = wtforms.TextAreaField( + _('Description of this work'), + description=_("""You can use + <a href="http://daringfireball.net/projects/markdown/basics"> + Markdown</a> for formatting.""")) + tags = wtforms.TextField( + _('Tags'), + [tag_length_validator], + description=_( + "Separate tags by commas.")) + license = wtforms.SelectField( + _('License'), + [wtforms.validators.Optional(),], + choices=licenses_as_choices()) + max_file_size = wtforms.HiddenField('') + upload_limit = wtforms.HiddenField('') + uploaded = wtforms.HiddenField('') + + return SubmitStartForm(form, **kwargs) class AddCollectionForm(wtforms.Form): title = wtforms.TextField( diff --git a/mediagoblin/submit/lib.py b/mediagoblin/submit/lib.py index 7c3b8ab3..c70e2731 100644 --- a/mediagoblin/submit/lib.py +++ b/mediagoblin/submit/lib.py @@ -16,11 +16,18 @@ import logging import uuid +from os.path import splitext + from werkzeug.utils import secure_filename from werkzeug.datastructures import FileStorage +from mediagoblin import mg_globals +from mediagoblin.tools.text import convert_to_tag_list_of_dicts +from mediagoblin.db.models import MediaEntry, ProcessingMetaData from mediagoblin.processing import mark_entry_failed -from mediagoblin.processing.task import process_media +from mediagoblin.processing.task import ProcessMedia +from mediagoblin.notifications import add_comment_subscription +from mediagoblin.media_types import sniff_media _log = logging.getLogger(__name__) @@ -36,6 +43,163 @@ def check_file_field(request, field_name): return retval +def new_upload_entry(user): + """ + Create a new MediaEntry for uploading + """ + entry = MediaEntry() + entry.uploader = user.id + entry.license = user.license_preference + return entry + + +def get_upload_file_limits(user): + """ + Get the upload_limit and max_file_size for this user + """ + if user.upload_limit >= 0: + upload_limit = user.upload_limit + else: + upload_limit = mg_globals.app_config.get('upload_limit', None) + + max_file_size = mg_globals.app_config.get('max_file_size', None) + + return upload_limit, max_file_size + + +class UploadLimitError(Exception): + """ + General exception for when an upload will be over some upload limit + """ + pass + + +class FileUploadLimit(UploadLimitError): + """ + This file is over the site upload limit + """ + pass + + +class UserUploadLimit(UploadLimitError): + """ + This file is over the user's particular upload limit + """ + pass + + +class UserPastUploadLimit(UploadLimitError): + """ + The user is *already* past their upload limit! + """ + pass + + + +def submit_media(mg_app, user, submitted_file, filename, + title=None, description=None, + license=None, tags_string=u"", + upload_limit=None, max_file_size=None, + callback_url=None, + # If provided we'll do the feed_url update, otherwise ignore + urlgen=None,): + """ + Args: + - mg_app: The MediaGoblinApp instantiated for this process + - user: the user object this media entry should be associated with + - submitted_file: the file-like object that has the + being-submitted file data in it (this object should really have + a .name attribute which is the filename on disk!) + - filename: the *original* filename of this. Not necessarily the + one on disk being referenced by submitted_file. + - title: title for this media entry + - description: description for this media entry + - license: license for this media entry + - tags_string: comma separated string of tags to be associated + with this entry + - upload_limit: size in megabytes that's the per-user upload limit + - max_file_size: maximum size each file can be that's uploaded + - callback_url: possible post-hook to call after submission + - urlgen: if provided, used to do the feed_url update + """ + if upload_limit and user.uploaded >= upload_limit: + raise UserPastUploadLimit() + + # If the filename contains non ascii generate a unique name + if not all(ord(c) < 128 for c in filename): + filename = unicode(uuid.uuid4()) + splitext(filename)[-1] + + # Sniff the submitted media to determine which + # media plugin should handle processing + media_type, media_manager = sniff_media(submitted_file, filename) + + # create entry and save in database + entry = new_upload_entry(user) + entry.media_type = media_type + entry.title = (title or unicode(splitext(filename)[0])) + + entry.description = description or u"" + + entry.license = license or None + + # Process the user's folksonomy "tags" + entry.tags = convert_to_tag_list_of_dicts(tags_string) + + # Generate a slug from the title + entry.generate_slug() + + queue_file = prepare_queue_task(mg_app, entry, filename) + + with queue_file: + queue_file.write(submitted_file.read()) + + # Get file size and round to 2 decimal places + file_size = mg_app.queue_store.get_file_size( + entry.queued_media_file) / (1024.0 * 1024) + file_size = float('{0:.2f}'.format(file_size)) + + # Check if file size is over the limit + if max_file_size and file_size >= max_file_size: + raise FileUploadLimit() + + # Check if user is over upload limit + if upload_limit and (user.uploaded + file_size) >= upload_limit: + raise UserUploadLimit() + + user.uploaded = user.uploaded + file_size + user.save() + + entry.file_size = file_size + + # Save now so we have this data before kicking off processing + entry.save() + + # Various "submit to stuff" things, callbackurl and this silly urlgen + # thing + if callback_url: + metadata = ProcessingMetaData() + metadata.media_entry = entry + metadata.callback_url = callback_url + metadata.save() + + if urlgen: + feed_url = urlgen( + 'mediagoblin.user_pages.atom_feed', + qualified=True, user=user.username) + else: + feed_url = None + + # Pass off to processing + # + # (... don't change entry after this point to avoid race + # conditions with changes to the document via processing code) + run_process_media(entry, feed_url) + + add_comment_subscription(user, entry) + + return entry + + def prepare_queue_task(app, entry, filename): """ Prepare a MediaEntry for the processing queue and get a queue file @@ -65,17 +229,21 @@ def prepare_queue_task(app, entry, filename): return queue_file -def run_process_media(entry, feed_url=None): +def run_process_media(entry, feed_url=None, + reprocess_action="initial", reprocess_info=None): """Process the media asynchronously :param entry: MediaEntry() instance to be processed. :param feed_url: A string indicating the feed_url that the PuSH servers should be notified of. This will be sth like: `request.urlgen( 'mediagoblin.user_pages.atom_feed',qualified=True, - user=request.user.username)`""" + user=request.user.username)` + :param reprocess_action: What particular action should be run. + :param reprocess_info: A dict containing all of the necessary reprocessing + info for the given media_type""" try: - process_media.apply_async( - [entry.id, feed_url], {}, + ProcessMedia().apply_async( + [entry.id, feed_url, reprocess_action, reprocess_info], {}, task_id=entry.queued_task_id) except BaseException as exc: # The purpose of this section is because when running in "lazy" diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py index e964ec12..42c378a8 100644 --- a/mediagoblin/submit/views.py +++ b/mediagoblin/submit/views.py @@ -16,32 +16,38 @@ from mediagoblin import messages import mediagoblin.mg_globals as mg_globals -from os.path import splitext import logging _log = logging.getLogger(__name__) -from mediagoblin.tools.text import convert_to_tag_list_of_dicts from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools.response import render_to_response, redirect -from mediagoblin.decorators import require_active_login +from mediagoblin.decorators import require_active_login, user_has_privilege from mediagoblin.submit import forms as submit_forms from mediagoblin.messages import add_message, SUCCESS -from mediagoblin.media_types import sniff_media, \ +from mediagoblin.media_types import \ InvalidFileType, FileTypeNotSupported -from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \ - run_process_media +from mediagoblin.submit.lib import \ + check_file_field, submit_media, get_upload_file_limits, \ + FileUploadLimit, UserUploadLimit, UserPastUploadLimit @require_active_login +@user_has_privilege(u'uploader') def submit_start(request): """ First view for submitting a file. """ - submit_form = submit_forms.SubmitStartForm(request.form, - license=request.user.license_preference) + upload_limit, max_file_size = get_upload_file_limits(request.user) + + submit_form = submit_forms.get_submit_start_form( + request.form, + license=request.user.license_preference, + max_file_size=max_file_size, + upload_limit=upload_limit, + uploaded=request.user.uploaded) if request.method == 'POST' and submit_form.validate(): if not check_file_field(request, 'file'): @@ -49,53 +55,39 @@ def submit_start(request): _(u'You must provide a file.')) else: try: - filename = request.files['file'].filename - - # Sniff the submitted media to determine which - # media plugin should handle processing - media_type, media_manager = sniff_media( - request.files['file']) - - # create entry and save in database - entry = request.db.MediaEntry() - entry.media_type = unicode(media_type) - entry.title = ( - unicode(submit_form.title.data) - or unicode(splitext(filename)[0])) - - entry.description = unicode(submit_form.description.data) - - entry.license = unicode(submit_form.license.data) or None - - entry.uploader = request.user.id - - # Process the user's folksonomy "tags" - entry.tags = convert_to_tag_list_of_dicts( - submit_form.tags.data) + submit_media( + mg_app=request.app, user=request.user, + submitted_file=request.files['file'], + filename=request.files['file'].filename, + title=unicode(submit_form.title.data), + description=unicode(submit_form.description.data), + license=unicode(submit_form.license.data) or None, + tags_string=submit_form.tags.data, + upload_limit=upload_limit, max_file_size=max_file_size, + urlgen=request.urlgen) - # Generate a slug from the title - entry.generate_slug() - - queue_file = prepare_queue_task(request.app, entry, filename) - - with queue_file: - queue_file.write(request.files['file'].stream.read()) - - # Save now so we have this data before kicking off processing - entry.save() - - # Pass off to processing - # - # (... don't change entry after this point to avoid race - # conditions with changes to the document via processing code) - feed_url = request.urlgen( - 'mediagoblin.user_pages.atom_feed', - qualified=True, user=request.user.username) - run_process_media(entry, feed_url) add_message(request, SUCCESS, _('Woohoo! Submitted!')) return redirect(request, "mediagoblin.user_pages.user_home", + user=request.user.username) + + + # Handle upload limit issues + except FileUploadLimit: + submit_form.file.errors.append( + _(u'Sorry, the file size is too big.')) + except UserUploadLimit: + submit_form.file.errors.append( + _('Sorry, uploading this file will put you over your' + ' upload limit.')) + except UserPastUploadLimit: + messages.add_message( + request, + messages.WARNING, + _('Sorry, you have reached your upload limit.')) + return redirect(request, "mediagoblin.user_pages.user_home", user=request.user.username) + except Exception as e: ''' This section is intended to catch exceptions raised in @@ -131,9 +123,9 @@ def add_collection(request, media=None): collection.generate_slug() # Make sure this user isn't duplicating an existing collection - existing_collection = request.db.Collection.find_one({ - 'creator': request.user.id, - 'title':collection.title}) + existing_collection = request.db.Collection.query.filter_by( + creator=request.user.id, + title=collection.title).first() if existing_collection: add_message(request, messages.ERROR, diff --git a/mediagoblin/templates/mediagoblin/api/authorize.html b/mediagoblin/templates/mediagoblin/api/authorize.html new file mode 100644 index 00000000..93cdc7e3 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/api/authorize.html @@ -0,0 +1,56 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% block title -%} + {% trans %}Authorization{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + +<h1>{% trans %}Authorize{% endtrans %}</h1> + +<p> + {% trans %}You are logged in as{% endtrans %} + <strong>{{user.username}}</strong> + <br /><br /> + + {% trans %}Do you want to authorize {% endtrans %} + {% if client.application_name -%} + <em>{{ client.application_name }}</em> + {%- else -%} + <em>{% trans %}an unknown application{% endtrans %}</em> + {%- endif %} + {% trans %} to access your account? {% endtrans %} + <br /><br /> + {% trans %}Applications with access to your account can: {% endtrans %} + <ul> + <li>{% trans %}Post new media as you{% endtrans %}</li> + <li>{% trans %}See your information (e.g profile, media, etc...){% endtrans %}</li> + <li>{% trans %}Change your information{% endtrans %}</li> + </ul> + <br /> + + <form method="POST"> + {{ csrf_token }} + {{ authorize_form.oauth_token }} + {{ authorize_form.oauth_verifier }} + <input type="submit" value="{% trans %}Authorize{% endtrans %}"> + </form> +</p> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/api/oob.html b/mediagoblin/templates/mediagoblin/api/oob.html new file mode 100644 index 00000000..d290472a --- /dev/null +++ b/mediagoblin/templates/mediagoblin/api/oob.html @@ -0,0 +1,33 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% block title -%} + {% trans %}Authorization Finished{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + +<h1>{% trans %}Authorization Complete{% endtrans %}</h1> + +<h4>{% trans %}Copy and paste this into your client:{% endtrans %}</h4> + +<p class="verifier"> + {{ oauth_request.verifier }} +</p> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html index 4a39059d..93cd82d9 100644 --- a/mediagoblin/templates/mediagoblin/auth/login.html +++ b/mediagoblin/templates/mediagoblin/auth/login.html @@ -20,8 +20,8 @@ {% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} {% block mediagoblin_head %} - <script type="text/javascript" - src="{{ request.staticdirect('/js/autofilledin_password.js') }}"></script> + {{ super() }} + {% template_hook("fp_head") %} {% endblock %} {% block title -%} @@ -29,7 +29,7 @@ {%- endblock %} {% block mediagoblin_content %} - <form action="{{ request.urlgen('mediagoblin.auth.login') }}" + <form action="{{ post_url }}" method="POST" enctype="multipart/form-data"> {{ csrf_token }} <div class="form_box"> @@ -39,17 +39,10 @@ {% trans %}Logging in failed!{% endtrans %} </div> {% endif %} - {% if allow_registration %} - <p> - {% trans %}Don't have an account yet?{% endtrans %} <a href="{{ request.urlgen('mediagoblin.auth.register') }}"> - {%- trans %}Create one here!{% endtrans %}</a> - </p> - {% endif %} - {{ wtforms_util.render_divs(login_form) }} - <p> - <a href="{{ request.urlgen('mediagoblin.auth.forgot_password') }}" id="forgot_password"> - {% trans %}Forgot your password?{% endtrans %}</a> - </p> + {% template_hook("create_account") %} + {% template_hook("login_link") %} + {{ wtforms_util.render_divs(login_form, True) }} + {% template_hook("fp_link") %} <div class="form_submit_buttons"> <input type="submit" value="{% trans %}Log in{% endtrans %}" class="button_form"/> </div> diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html index 6dff0207..a7b8033f 100644 --- a/mediagoblin/templates/mediagoblin/auth/register.html +++ b/mediagoblin/templates/mediagoblin/auth/register.html @@ -30,11 +30,12 @@ {% block mediagoblin_content %} - <form action="{{ request.urlgen('mediagoblin.auth.register') }}" + <form action="{{ post_url }}" method="POST" enctype="multipart/form-data"> <div class="form_box"> <h1>{% trans %}Create an account!{% endtrans %}</h1> - {{ wtforms_util.render_divs(register_form) }} + {% template_hook("register_link") %} + {{ wtforms_util.render_divs(register_form, True) }} {{ csrf_token }} <div class="form_submit_buttons"> <input type="submit" value="{% trans %}Create{% endtrans %}" @@ -42,6 +43,4 @@ </div> </div> </form> -<!-- Focus the username field by default --> -<script>$(document).ready(function(){$("#username").focus();});</script> {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/banned.html b/mediagoblin/templates/mediagoblin/banned.html new file mode 100644 index 00000000..0b5a6884 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/banned.html @@ -0,0 +1,35 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% block title %}{% trans %}You are Banned.{% endtrans %}{% endblock %} + +{% block mediagoblin_content %} + <img class="right_align" src="{{ request.staticdirect('/images/404.png') }}" + alt="{% trans %}Image of goblin stressing out{% endtrans %}" /> + + <h1>{% trans %}You have been banned{% endtrans %} + {% if expiration_date %} + {% trans until_when=expiration_date %}until {{ until_when }}{% endtrans %} + {% else %} + {% trans %}indefinitely{% endtrans %} + {% endif %} + </h2> + <p>{{ reason|safe }}</p> + <div class="clear"></div> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html index 83bc65d4..6d49ff47 100644 --- a/mediagoblin/templates/mediagoblin/base.html +++ b/mediagoblin/templates/mediagoblin/base.html @@ -18,12 +18,16 @@ <!doctype html> <html -{% block mediagoblin_html_tag %} -{% endblock mediagoblin_html_tag %} -> - <head {% if is_rtl %} dir="rtl" {% endif %}> + {% block mediagoblin_html_tag %} + {% endblock mediagoblin_html_tag %} + {% if is_rtl -%} + dir="rtl" + {%- endif -%} + > + <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <title>{% block title %}{{ app_config['html_title'] }}{% endblock %}</title> <link rel="stylesheet" type="text/css" href="{{ request.staticdirect('/css/extlib/reset.css') }}"/> @@ -35,6 +39,11 @@ src="{{ request.staticdirect('/js/extlib/jquery.js') }}"></script> <script type="text/javascript" src="{{ request.staticdirect('/js/header_dropdown.js') }}"></script> + <script type="text/javascript" + src="{{ request.staticdirect('/js/notifications.js') }}"></script> + <script> + var mark_all_comments_seen_url = "{{ request.urlgen('mediagoblin.notifications.mark_all_comment_notifications_seen') }}" + </script> {# For clarification, the difference between the extra_head.html template # and the head template hook is that the former should be used by @@ -49,8 +58,7 @@ {% endblock mediagoblin_head %} </head> <body> - <div {% if is_rtl %} dir="rtl" {% endif %}> - {% include 'mediagoblin/bits/body-start.html' %} + {% include 'mediagoblin/bits/body_start.html' %} {% block mediagoblin_body %} {% block mediagoblin_header %} <header> @@ -58,26 +66,53 @@ {% block mediagoblin_header_title %}{% endblock %} <div class="header_right"> {%- if request.user %} - {% if request.user and request.user.status == 'active' %} - <div class="button_action header_dropdown_down">▼</div> - <div class="button_action header_dropdown_up">▲</div> - {% elif request.user and request.user.status == "needs_email_verification" %} + {% if request.user and + request.user.has_privilege('active') and + not request.user.is_banned() %} + + {% set notification_count = get_notification_count(request.user.id) %} + {% if notification_count %} + <a href="javascript:;" class="notification-gem button_action" title="Notifications"> + {{ notification_count }}</a> + {% endif %} + <a href="javascript:;" class="button_action header_dropdown_down">▼</a> + <a href="javascript:;" class="button_action header_dropdown_up">▲</a> + {% elif request.user and not request.user.has_privilege('active') %} {# the following link should only appear when verification is needed #} <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', user=request.user.username) }}" class="button_action_highlight"> {% trans %}Verify your email!{% endtrans %}</a> - or <a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}log out{% endtrans %}</a> + or <a id="logout" href= + {% if persona is not defined %} + "{{ request.urlgen('mediagoblin.auth.logout') }}" + {% else %} + "javascript:;" + {% endif %} + >{% trans %}log out{% endtrans %}</a> + {% elif request.user and request.user.is_banned() %} + <a id="logout" href= + {% if persona is not defined %} + "{{ request.urlgen('mediagoblin.auth.logout') }}" + {% else %} + "javascript:;" + {% endif %} + >{% trans %}log out{% endtrans %}</a> + {% endif %} + {%- elif auth %} + <a href= + {% if persona_auth is defined %} + "javascript:;" id="persona_login" + {% else %} + "{{ request.urlgen('mediagoblin.auth.login') }}" {% endif %} - {%- else %} - <a href="{{ request.urlgen('mediagoblin.auth.login') }}?next={{ - request.base_url|urlencode }}"> + > {%- trans %}Log in{% endtrans -%} </a> {%- endif %} </div> <div class="clear"></div> - {% if request.user and request.user.status == 'active' %} + {% if request.user and request.user.has_privilege('active') %} <div class="header_dropdown"> <p> <span class="dropdown_title"> @@ -95,7 +130,14 @@ {%- trans %}Media processing panel{% endtrans -%} </a> · - <a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}Log out{% endtrans %}</a> + {% template_hook("blog_dashboard_home") %} + <a id="logout" href= + {% if persona is not defined %} + "{{ request.urlgen('mediagoblin.auth.logout') }}" + {% else %} + "javascript:;" + {% endif %} + >{% trans %}Log out{% endtrans %}</a> </p> <a class="button_action" href="{{ request.urlgen('mediagoblin.submit.start') }}"> {%- trans %}Add media{% endtrans -%} @@ -103,38 +145,40 @@ <a class="button_action" href="{{ request.urlgen('mediagoblin.submit.collection') }}"> {%- trans %}Create new collection{% endtrans -%} </a> - {% if request.user.is_admin %} + {% if request.user.has_privilege('admin','moderator') %} <p> - <span class="dropdown_title">Admin powers:</span> - <a href="{{ request.urlgen('mediagoblin.admin.panel') }}"> + <span class="dropdown_title">Moderation powers:</span> + <a href="{{ request.urlgen('mediagoblin.moderation.media_panel') }}"> {%- trans %}Media processing panel{% endtrans -%} </a> + · + <a href="{{ request.urlgen('mediagoblin.moderation.users') }}"> + {%- trans %}User management panel{% endtrans -%} + </a> + · + <a href="{{ request.urlgen('mediagoblin.moderation.reports') }}"> + {%- trans %}Report management panel{% endtrans -%} + </a> </p> {% endif %} + {% include 'mediagoblin/fragments/header_notifications.html' %} </div> {% endif %} </header> {% endblock %} <div class="container"> - {% include 'mediagoblin/bits/above-content.html' %} + {% include 'mediagoblin/bits/above_content.html' %} <div class="mediagoblin_content"> {% include "mediagoblin/utils/messages.html" %} {% block mediagoblin_content %} {% endblock mediagoblin_content %} + {% if csrf_token is defined %} + {% template_hook("persona_form") %} + {% endif %} </div> - {%- block mediagoblin_footer %} - <footer> - {% trans -%} - Powered by <a href="http://mediagoblin.org/" title='Version {{ version }}'>MediaGoblin</a>, a <a href="http://gnu.org/">GNU</a> project. - {%- endtrans %} - {% trans source_link=app_config['source_link'] -%} - Released under the <a href="http://www.fsf.org/licensing/licenses/agpl-3.0.html">AGPL</a>. <a href="{{ source_link }}">Source code</a> available. - {%- endtrans %} - </footer> - {%- endblock mediagoblin_footer %} + {%- include "mediagoblin/bits/base_footer.html" %} </div> {%- endblock mediagoblin_body %} - {% include 'mediagoblin/bits/body-end.html' %} - </div> - </body> + {% include 'mediagoblin/bits/body_end.html' %} + </body> </html> diff --git a/mediagoblin/templates/mediagoblin/bits/above-content.html b/mediagoblin/templates/mediagoblin/bits/above_content.html index bb7b9762..bb7b9762 100644 --- a/mediagoblin/templates/mediagoblin/bits/above-content.html +++ b/mediagoblin/templates/mediagoblin/bits/above_content.html diff --git a/mediagoblin/templates/mediagoblin/bits/base_footer.html b/mediagoblin/templates/mediagoblin/bits/base_footer.html new file mode 100644 index 00000000..84397be2 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/bits/base_footer.html @@ -0,0 +1,35 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011-2013 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/>. +#} + +{%- block mediagoblin_footer %} + <footer> + {% trans -%} + Powered by <a href="http://mediagoblin.org/" title='Version {{ version }}'>MediaGoblin</a>, a <a href="http://gnu.org/">GNU</a> project. + {%- endtrans %} + {% trans source_link=app_config['source_link'] -%} + Released under the <a href="http://www.fsf.org/licensing/licenses/agpl-3.0.html">AGPL</a>. <a href="{{ source_link }}">Source code</a> available. + {%- endtrans %} + {% if app_config['show_tos'] %} + <p class="fine_print"> + <a href="{{ request.urlgen('terms_of_service') }}"> + {%- trans %}Terms of Service{%- endtrans %} + </a> + </p> + {% endif %} + </footer> +{%- endblock mediagoblin_footer -%} diff --git a/mediagoblin/templates/mediagoblin/bits/body_end.html b/mediagoblin/templates/mediagoblin/bits/body_end.html new file mode 100644 index 00000000..c8f5e2d6 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/bits/body_end.html @@ -0,0 +1,19 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +-#} + +{% template_hook("persona_end") %} diff --git a/mediagoblin/templates/mediagoblin/bits/body-end.html b/mediagoblin/templates/mediagoblin/bits/body_start.html index bb7b9762..bb7b9762 100644 --- a/mediagoblin/templates/mediagoblin/bits/body-end.html +++ b/mediagoblin/templates/mediagoblin/bits/body_start.html diff --git a/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html b/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html new file mode 100644 index 00000000..4e55e618 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html @@ -0,0 +1,47 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% if request.user %} + <h1>{% trans %}Explore{% endtrans %}</h1> + {% else %} + <img class="right_align" src="{{ request.staticdirect('/images/home_goblin.png') }}" /> + <h1>{% trans %}Hi there, welcome to this MediaGoblin site!{% endtrans %}</h1> + <p>{% trans %}This site is running <a href="http://mediagoblin.org">MediaGoblin</a>, an extraordinarily great piece of media hosting software.{% endtrans %}</p> + {% if auth %} + <p>{% trans %}To add your own media, place comments, 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> + <a class="button_action_highlight" href= + {% if persona_auth is defined %} + "javascript:;" id="persona_login1" + {% else %} + "{{ request.urlgen('mediagoblin.auth.register') }}" + {% endif %} + {% trans %} + >Create an account at this site</a> + or + {%- endtrans %} + {% endif %} + {% endif %} + {% trans %} + <a class="button_action" href="http://mediagoblin.readthedocs.org/">Set up MediaGoblin on your own server</a> + {%- endtrans %} + + <div class="clear"></div> + {% endif %} + diff --git a/mediagoblin/templates/mediagoblin/edit/change_email.html b/mediagoblin/templates/mediagoblin/edit/change_email.html new file mode 100644 index 00000000..76cc4771 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/edit/change_email.html @@ -0,0 +1,45 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans username=user.username -%} + Changing {{ username }}'s email + {%- endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + <form action="{{ request.urlgen('mediagoblin.edit.email') }}" + method="POST" enctype="multipart/form-data"> + <div class="form_box edit_box"> + <h1> + {%- trans username=user.username -%} + Changing {{ username }}'s email + {%- endtrans -%} + </h1> + {{ wtforms_util.render_divs(form, True) }} + {{ csrf_token }} + <div class="form_submit_buttons"> + <input type="submit" value="{% trans %}Save{% endtrans %}" + class="button_form" /> + </div> + </div> + </form> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html index 7fe2c031..574fe459 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_account.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html @@ -41,16 +41,11 @@ Changing {{ username }}'s account settings {%- endtrans -%} </h1> - {{ wtforms_util.render_field_div(form.old_password) }} - {{ wtforms_util.render_field_div(form.new_password) }} - <div class="form_field_input"> - <p>{{ form.wants_comment_notification }} - {{ wtforms_util.render_label(form.wants_comment_notification) }}</p> - </div> - {{- wtforms_util.render_field_div(form.license_preference) }} - <div class="form_submit_buttons"> + {% template_hook("edit_link") %} + {{ wtforms_util.render_divs(form, True) }} + <div class="form_submit_buttons"> <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button_form" /> - {{ csrf_token }} + {{ csrf_token }} </div> </div> </form> @@ -58,5 +53,16 @@ <a href="{{ request.urlgen('mediagoblin.edit.delete_account') }}"> {%- trans %}Delete my account{% endtrans -%} </a> + · + {% template_hook("edit_link") %} + <a href="{{ request.urlgen('mediagoblin.edit.email') }}"> + {% trans %}Email{% endtrans %} + </a> + {% if pass_auth is defined %} + · + <a href="{{ request.urlgen('mediagoblin.plugins.basic_auth.edit.pass') }}"> + {% trans %}Password{% endtrans %} + </a> + {% endif %} </div> {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/edit/verification.txt b/mediagoblin/templates/mediagoblin/edit/verification.txt new file mode 100644 index 00000000..d53cd5e8 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/edit/verification.txt @@ -0,0 +1,29 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +-#} + +{% trans username=username, verification_url=verification_url|safe -%} +Hi, + +We wanted to verify that you are {{ username }}. If this is the case, then +please follow the link below to verify your new email address. + +{{ verification_url }} + +If you are not {{ username }} or didn't request an email change, you can ignore +this email. +{%- endtrans %} diff --git a/mediagoblin/templates/mediagoblin/extra_head.html b/mediagoblin/templates/mediagoblin/extra_head.html index 973e2b48..847cfcc7 100644 --- a/mediagoblin/templates/mediagoblin/extra_head.html +++ b/mediagoblin/templates/mediagoblin/extra_head.html @@ -17,3 +17,19 @@ -#} {# Add extra head declarations here for your theme, if appropriate #} + +<script type="text/javascript" + src="{{request.staticdirect('extlib/tinymce/js/tinymce/tinymce.min.js')}}"></script> + + <script type="text/javascript"> + tinyMCE.init({ + selector: "div.blog_form_field_input textarea", + height: 300, + width: 800, + plugins: [ + "advlist autolink link image lists charmap print preview hr anchor pagebreak spellchecker", + "searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking", + "save table contextmenu directionality emoticons template paste textcolor" + ] + }) +</script> diff --git a/mediagoblin/templates/mediagoblin/fragments/header_notifications.html b/mediagoblin/templates/mediagoblin/fragments/header_notifications.html new file mode 100644 index 00000000..55759a39 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/fragments/header_notifications.html @@ -0,0 +1,44 @@ +{% set notifications = get_notifications(request.user.id) %} +{% if notifications %} + <div class="header_notifications"> + <h3>{% trans %}New comments{% endtrans %}</h3> + <ul> + {% for notification in notifications %} + {% set comment = notification.subject %} + {% set comment_author = comment.get_author %} + {% set media = comment.get_entry %} + <li class="comment_wrapper"> + <div class="comment_author"> + <img src="{{ request.staticdirect('/images/icon_comment.png') }}" /> + <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', + user=comment_author.username) }}" + class="comment_authorlink"> + {{- comment_author.username -}} + </a> + <a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment', + comment=comment.id, + user=media.get_uploader.username, + media=media.slug_or_id) }}#comment" + class="comment_whenlink"> + <span title='{{- comment.created.strftime("%I:%M%p %Y-%m-%d") -}}'> + {%- trans formatted_time=timesince(comment.created) -%} + {{ formatted_time }} ago + {%- endtrans -%} + </span> + </a>: + </div> + <div class="comment_content"> + {% autoescape False -%} + {{ comment.content_html }} + {%- endautoescape %} + </div> + + </li> + {% endfor %} + </ul> + <a href="{{ request.urlgen('mediagoblin.notifications.mark_all_comment_notifications_seen') }}?next={{ + request.base_url|urlencode }}" id="mark_all_comments_seen"> + {% trans %}Mark all read{% endtrans %} + </a> + </div> +{% endif %} diff --git a/mediagoblin/templates/mediagoblin/media_displays/blogpost.html b/mediagoblin/templates/mediagoblin/media_displays/blogpost.html new file mode 100644 index 00000000..ca3441b9 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/media_displays/blogpost.html @@ -0,0 +1,33 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% extends 'mediagoblin/user_pages/blog_media.html' %} + +{% block mediagoblin_head %} + {{ super() }} +{% endblock %} + +{% block mediagoblin_media %} +<h1> {{media.title}}</h1> +<p>{{media.description|safe}}</p> + +{% endblock %} + + + + diff --git a/mediagoblin/templates/mediagoblin/media_displays/image.html b/mediagoblin/templates/mediagoblin/media_displays/image.html index 158dd67f..d0050f50 100644 --- a/mediagoblin/templates/mediagoblin/media_displays/image.html +++ b/mediagoblin/templates/mediagoblin/media_displays/image.html @@ -27,3 +27,20 @@ {{ super() }} {% template_hook("image_sideinfo") %} {% endblock %} + +{% block mediagoblin_after_added_sidebar %} + {% if app_config['original_date_visible'] %} + {% set original_date = media.media_manager.get_original_date() %} + + {% if original_date %} + <h3>{% trans %}Created{% endtrans %}</h3> + + <p><span title="{{ original_date.strftime("%I:%M%p %Y-%m-%d") }}"> + {%- trans formatted_time=timesince(original_date) -%} + {{ formatted_time }} ago + {%- endtrans -%} + </span></p> + {%- endif %} + {% endif %} +{% endblock %} + diff --git a/mediagoblin/templates/mediagoblin/media_displays/pdf.html b/mediagoblin/templates/mediagoblin/media_displays/pdf.html index e946f3ab..a615cba6 100644 --- a/mediagoblin/templates/mediagoblin/media_displays/pdf.html +++ b/mediagoblin/templates/mediagoblin/media_displays/pdf.html @@ -29,7 +29,7 @@ media.media_files['original']) %} {% endif %} -{% set pdf_js = global_config.get('media_type:mediagoblin.media_types.pdf', {}).get('pdf_js', False) %} +{% set pdf_js = global_config['plugins'].get('mediagoblin.media_types.pdf', {}).get('pdf_js', False) %} {% if pdf_js %} {% block mediagoblin_html_tag %} @@ -46,19 +46,21 @@ {%- endblock %} {% block mediagoblin_media %} -{% if pdf_js %} -<iframe width=640px height=480px - src="{{ request.staticdirect('/extlib/pdf.js/web/viewer.html') }}?file={{ pdf_view }} "> -</iframe> - -{% else %} - <a href="{{ pdf_view }}"> - <img id="medium" - class="media_image" - src="{{ medium_view }}" - alt="{% trans media_title=media.title -%} Image for {{ media_title}}{% endtrans %}"/> - </a> -{% endif %} + {% if pdf_js %} + <iframe width="640px" height="480px" + src="{{ request.staticdirect('/extlib/pdf.js/web/viewer.html') }}?file={{ pdf_view }} "> + </iframe> + {% else %} + <a href="{{ pdf_view }}"> + <img id="medium" + class="media_image" + src="{{ medium_view }}" + alt=" + {%- trans media_title=media.title -%} + Image for {{ media_title}} + {%- endtrans %}"/> + </a> + {% endif %} {% endblock %} {% block mediagoblin_sidebar %} diff --git a/mediagoblin/templates/mediagoblin/media_displays/stl.html b/mediagoblin/templates/mediagoblin/media_displays/stl.html index a89e0b4f..bc12ce4e 100644 --- a/mediagoblin/templates/mediagoblin/media_displays/stl.html +++ b/mediagoblin/templates/mediagoblin/media_displays/stl.html @@ -108,32 +108,26 @@ window.show_things = function () { <div style="padding: 4px;"> - <a class="button_action" onclick="show('perspective');" - title="{%- trans %}Toggle Rotate{% endtrans -%}"> + <a class="button_action" onclick="show('perspective');"> {%- trans %}Perspective{% endtrans -%} </a> - <a class="button_action" onclick="show('front_view');" - title="{%- trans %}Front{% endtrans -%}"> + <a class="button_action" onclick="show('front_view');"> {%- trans %}Front{% endtrans -%} </a> - <a class="button_action" onclick="show('top_view');" - title="{%- trans %}Top{% endtrans -%}"> + <a class="button_action" onclick="show('top_view');"> {%- trans %}Top{% endtrans -%} </a> - <a class="button_action" onclick="show('side_view');" - title="{%- trans %}Side{% endtrans -%}"> + <a class="button_action" onclick="show('side_view');"> {%- trans %}Side{% endtrans -%} </a> {% if media.media_data.file_type == "stl" %} <a id="webgl_button" class="button_action" - onclick="show_things();" - title="{%- trans %}WebGL{% endtrans -%}"> + onclick="show_things();"> {%- trans %}WebGL{% endtrans -%} </a> {% endif %} <a class="button_action" href="{{ model_download }}" - title="{%- trans %}Download{% endtrans -%}" style="float:right;"> {%- trans %}Download model{% endtrans -%} </a> diff --git a/mediagoblin/templates/mediagoblin/media_displays/video.html b/mediagoblin/templates/mediagoblin/media_displays/video.html index b0854c9f..9386ffcf 100644 --- a/mediagoblin/templates/mediagoblin/media_displays/video.html +++ b/mediagoblin/templates/mediagoblin/media_displays/video.html @@ -21,17 +21,36 @@ {% block mediagoblin_head -%} {{ super() }} <script type="text/javascript" src="{{ - request.staticdirect('/extlib/video-js/video.min.js') }}"></script> - <link href="{{ request.staticdirect('/css/vjs-mg-skin.css') }}" + request.staticdirect('/extlib/video-js/video.js') }}"></script> + {# Sadly commented out till we can get the mediagoblin skin ported over + # to the newest video.js release ;\ #} + {# + <link href="{{ request.staticdirect('/css/vjs-mg-skin.css') }}" + rel="stylesheet"> + #} + <link href="{{ + request.staticdirect('/extlib/video-js/video-js.css') }}" rel="stylesheet"> + + <style type="text/css"> + .vjs-default-skin .vjs-big-play-button + { + top: 50%; + left: 50%; + margin: -1.5em auto auto -2em; + } + .vjs-play-progress, .vjs-volume-level { + background-color: #86D4B1 !important; + } + </style> {%- endblock %} {% block mediagoblin_media %} {% set display_type, display_path = media.get_display_media() %} <video controls - {% if global_config['media_type:mediagoblin.media_types.video']['auto_play'] %}autoplay{% endif %} - preload="auto" class="video-js vjs-mg-skin" + {% if global_config['plugins']['mediagoblin.media_types.video']['auto_play'] %}autoplay{% endif %} + preload="auto" class="video-js vjs-default-skin" data-setup='{"height": {{ media.media_data.height }}, "width": {{ media.media_data.width }} }'> <source src="{{ request.app.public_store.file_url(display_path) }}" @@ -62,11 +81,11 @@ </a> </li> {% endif %} - {% if 'webm_640' in media.media_files %} + {% if 'webm_video' in media.media_files %} <li> <a href="{{ request.app.public_store.file_url( - media.media_files.webm_640) }}"> - {%- trans %}WebM file (640p; VP8/Vorbis){% endtrans -%} + media.media_files.webm_video) }}"> + {%- trans %}WebM file (VP8/Vorbis){% endtrans -%} </a> </li> {% endif %} diff --git a/mediagoblin/templates/mediagoblin/admin/panel.html b/mediagoblin/templates/mediagoblin/moderation/media_panel.html index 1c3c866e..3c929d4f 100644 --- a/mediagoblin/templates/mediagoblin/admin/panel.html +++ b/mediagoblin/templates/mediagoblin/moderation/media_panel.html @@ -21,6 +21,7 @@ {% trans %}Media processing panel{% endtrans %} — {{ super() }} {%- endblock %} + {% block mediagoblin_content %} <h1>{% trans %}Media processing panel{% endtrans %}</h1> @@ -28,7 +29,7 @@ <p> {% trans %}Here you can track the state of media being processed on this instance.{% endtrans %} </p> - + <h2>{% trans %}Media in-processing{% endtrans %}</h2> {% if processing_entries.count() %} @@ -56,7 +57,7 @@ </table> {% else %} <p><em>{% trans %}No media in-processing{% endtrans %}</em></p> -{% endif %} +{% endif %} <h2>{% trans %}These uploads failed to process:{% endtrans %}</h2> {% if failed_entries.count() %} diff --git a/mediagoblin/templates/mediagoblin/moderation/report.html b/mediagoblin/templates/mediagoblin/moderation/report.html new file mode 100644 index 00000000..cedbd49a --- /dev/null +++ b/mediagoblin/templates/mediagoblin/moderation/report.html @@ -0,0 +1,161 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{%- extends "mediagoblin/base.html" %} +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} +{%- block mediagoblin_head %} + <script src="{{ request.staticdirect('/js/setup_report_forms.js') }}"> + </script> +{% endblock %} + +{%- block mediagoblin_content %} +{% if not report %} + {% trans %}Sorry, no such report found.{% endtrans %} +{% else %} + <a href="{{ request.urlgen('mediagoblin.moderation.reports') }}" + class="return_to_panel button_action" + title="Return to Reports Panel"> + {% trans %}Return to Reports Panel{% endtrans %}</a> + <h2>{% trans %}Report{% endtrans %} #{{ report.id }}</h2> + {% if report.is_comment_report() and report.comment %} + + {% trans %}Reported comment{% endtrans %}: + {% set comment = report.comment %} + {% set reported_user = comment.get_author %} + <div id="comment-{{ comment.id }}" + class="comment_wrapper"> + <div class="comment_author"> + <img src="{{ request.staticdirect('/images/icon_comment.png') }}" /> + <a href="{{ request.urlgen('mediagoblin.moderation.users_detail', + user=comment.get_author.username) }}" + class="comment_authorlink"> + {{- reported_user.username -}} + </a> + <a href="{{ request.urlgen( + 'mediagoblin.user_pages.media_home.view_comment', + comment=comment.id, + user=comment.get_media_entry.get_uploader.username, + media=comment.get_media_entry.slug_or_id) }}#comment" + class="comment_whenlink"> + <span title='{{- comment.created.strftime("%I:%M%p %Y-%m-%d") -}}'> + {%- trans formatted_time=timesince(comment.created) -%} + {{ formatted_time }} ago + {%- endtrans -%} + </span></a>: + </div> + <div class=comment_content> + {% autoescape False %} + {{ comment.content_html }} + {% endautoescape %} + </div> + </div> + {% elif report.is_media_entry_report() and report.media_entry %} + + {% set media_entry = report.media_entry %} + <div class="media_thumbnail"> + <a href="{{ request.urlgen('mediagoblin.user_pages.media_home', + user=media_entry.get_uploader.username, + media=media_entry.slug_or_id) }}"> + <img src="{{ media_entry.thumb_url}}"/></a> + <a href="{{ request.urlgen('mediagoblin.user_pages.media_home', + user=media_entry.get_uploader.username, + media=media_entry.slug_or_id) }}" class=thumb_entry_title> + {{ media_entry.title }}</a> + </div> + <div class=clear></div> + <p> + {% trans user_name=report.reported_user.username, + user_url=request.urlgen( + 'mediagoblin.moderation.users_detail', + user=report.reported_user.username) %} + â– Reported media by <a href="{{ user_url }}">{{ user_name }}</a> + {% endtrans %} + </p> + <div class=clear></div> + {% else %} + <h2>{% trans user_url=request.urlgen( + 'mediagoblin.moderation.users_detail', + user=report.reporter.username), + user_name=report.reported_user.username %} + CONTENT BY + <a href="{{ user_url }}"> {{ user_name }}</a> + HAS BEEN DELETED + {% endtrans %} + </h2> + {% endif %} + Reason for report: + <div id="report-{{ report.id }}" + class="report_wrapper"> + <div class="report_author"> + <img src="{{ request.staticdirect( + '/images/icon_clipboard_alert.png') }}" + alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license. + Distributed by the GNOME project http://www.gnome.org" /> + <a href="{{ request.urlgen('mediagoblin.moderation.users_detail', + user=report.reporter.username) }}" + class="report_authorlink"> + {{- report.reporter.username -}} + </a> + <a href="{{ request.urlgen('mediagoblin.moderation.reports_detail', + report_id=report.id) }}" + class="report_whenlink"> + <span title='{{- report.created.strftime("%I:%M%p %Y-%m-%d") -}}'> + {%- trans formatted_time=timesince(report.created) -%} + {{ formatted_time }} ago + {%- endtrans -%} + </span> + </a> + </div> + <div class="report_content"> + {{ report.report_content }} + </div> + </div> + {% if not report.is_archived_report() and + not (report.reported_user.has_privilege('admin') and + not request.user.has_privilege('admin')) %} + <input type=button value="{% trans %}Resolve{% endtrans %}" id=open_resolution_form /> + <form action="" method="POST" id=resolution_form> + {{ wtforms_util.render_divs(form) }} + {{ csrf_token }} + <input type=submit id="submit_this_report" value="{% trans %}Resolve This Report{% endtrans %}"/> + </form> + <script> + $(document).ready(function() { + init_report_resolution_form(); + }); + </script> + {% elif report.is_archived_report() %} + <h2><img src="{{ request.staticdirect('/images/icon_clipboard.png') }}" + alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license. + Distributed by the GNOME project http://www.gnome.org" /> + {% trans %}Status{% endtrans %}: + </h2> + <b>{% trans %}RESOLVED{% endtrans %}</b> + {{ report.resolved.strftime("%I:%M%p %Y-%m-%d") }} + <pre> + <p>{{ report.result }}</p> + </pre> + {% else %} + <input type=button disabled=disabled value="{% trans %}Resolve This Report{% endtrans %}"/> + <p> + {% trans -%} + You cannot take action against an administrator + {%- endtrans %} + </p> + {% endif %} +{% endif %} +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/moderation/report_panel.html b/mediagoblin/templates/mediagoblin/moderation/report_panel.html new file mode 100644 index 00000000..95b6be80 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/moderation/report_panel.html @@ -0,0 +1,202 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans %}Report panel{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + +<h1>{% trans %}Report panel{% endtrans %}</h1> + +<p> + {% trans %} + Here you can look up open reports that have been filed by users. + {% endtrans %} +</p> + +<h2>{% trans %}Active Reports Filed{% endtrans %}</h2> +{% if report_list.count() %} + {% if not active_settings.last_page == 1 %} + {% if 'active_p='~active_settings.current_page in request.query_string %} + {% set query_string = request.query_string %}{% else %} + {% set query_string = +'active_p='~active_settings.current_page~"&"+request.query_string %} + {% endif %} + <div class="right_align"> + {% set first_vis = active_settings.current_page-3 %} + {% set last_vis = active_settings.current_page+3 %} + {% set curr_page = active_settings.current_page %} + {% if 1 == curr_page %}<b>1</b>{% else %} + <a href ="?{{ query_string.replace( + 'active_p='~active_settings.current_page, + 'active_p='~1) }}"> + 1</a>{% endif %} + {% if first_vis > 1 %}...{% endif %} + {% for p in range(first_vis,last_vis+1) %} + {% if p > 1 and p < active_settings.last_page and +curr_page !=p %} + <a href="?{{ query_string.replace( + 'active_p='~active_settings.current_page, + 'active_p='~p) }}"> + {{ p }}</a> + {% elif p > 1 and p < active_settings.last_page %} + <b>{{ p }}</b> + {% endif %} + {% endfor %} + {% if last_vis < active_settings.last_page %}...{% endif %} + {% if active_settings.last_page != curr_page %} + <a href ="?{{ query_string.replace( + 'active_p='~active_settings.current_page, + 'active_p='~active_settings.last_page) }}"> + {{ active_settings.last_page }}</a> + {% else %}<b>{{ active_settings.last_page }}</b> + {% endif %} + </div> + {% endif %} + <table class="admin_panel processing"> + <tr> + <th></th> + <th>{% trans %}Offender{% endtrans %}</th> + <th>{% trans %}When Reported{% endtrans %}</th> + <th>{% trans %}Reported By{% endtrans %}</th> + <th>{% trans %}Reason{% endtrans %}</th> + </tr> + {% for report in report_list %} + <tr> + {% if report.discriminator == "comment_report" %} + <td> + <img + src="{{ request.staticdirect( + '/images/icon_clipboard_alert.png') }}" + alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license. + Distributed by the GNOME project http://www.gnome.org" /> + <a href="{{ request.urlgen( + 'mediagoblin.moderation.reports_detail', + report_id=report.id) }}"> + {% trans report_id=report.id %} + Comment Report #{{ report_id }} + {% endtrans %} + </a> + </td> + {% elif report.discriminator == "media_report" %} + <td> + <img + src="{{ request.staticdirect( + '/images/icon_clipboard_alert.png') }}" + alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license. + Distributed by the GNOME project http://www.gnome.org" /> + <a href="{{ request.urlgen( + 'mediagoblin.moderation.reports_detail', + report_id=report.id) }}"> + {% trans report_id=report.id %} + Media Report #{{ report_id }} + {% endtrans %} + </a> + </td> + {% endif %} + <td>{{ report.reported_user.username }}</td> + <td>{{ report.created.strftime("%F %R") }}</td> + <td>{{ report.reporter.username }}</td> + <td>{{ report.report_content[0:20] }}...</td> + </tr> + {% endfor %} + </table> +{% else %} + <p><em>{% trans %}No open reports found.{% endtrans %}</em></p> +{% endif %} +<h2>{% trans %}Closed Reports{% endtrans %}</h2> +{% if closed_report_list.count() %} + {% if not closed_settings.last_page == 1 %} + {% if 'closed_p='~closed_settings.current_page in request.query_string %} + {% set query_string = request.query_string %}{% else %} + {% set query_string = +'closed_p='~closed_settings.current_page~"&"+request.query_string %} + {% endif %} + <div class="right_align"> + {% set first_vis = closed_settings.current_page-3 %} + {% set last_vis = closed_settings.current_page+3 %} + {% set curr_page = closed_settings.current_page %} + {% if not curr_page==1 %} + <a href ="?{{ query_string.replace( + 'closed_p='~closed_settings.current_page, + 'closed_p='~1) }}">1</a> + {% else %} + <b>1 </b> + {% endif %} + {% if first_vis > 1 %}...{% endif %} + {% for p in range(first_vis,last_vis+1) %} + {% if p > 1 and p < closed_settings.last_page and +curr_page !=p %} + <a href="?{{ query_string.replace( + 'closed_p='~closed_settings.current_page, + 'closed_p='~p) }}"> + {{ p }}</a> + + {% elif p > 1 and p < closed_settings.last_page %} + <b>{{ p }}</b> + {% endif %} + {% endfor %} + {% if last_vis < closed_settings.last_page %}...{% endif %} + {% if curr_page != closed_settings.last_page %} + <a href ="?{{ query_string.replace( + 'closed_p='~closed_settings.current_page, + 'closed_p='~closed_settings.last_page) }}"> + {{ closed_settings.last_page }}</a> + {% else %}<b>{{ closed_settings.last_page }}</b> + {% endif %} + </div> + {% endif %} + <table class="media_panel processing"> + <tr> + <th></th> + <th>{% trans %}Resolved{% endtrans %}</th> + <th>{% trans %}Offender{% endtrans %}</th> + <th>{% trans %}Action Taken{% endtrans %}</th> + <th>{% trans %}Reported By{% endtrans %}</th> + <th>{% trans %}Reason{% endtrans %}</th> + </tr> + {% for report in closed_report_list %} + <tr> + <td> + <img + src="{{ request.staticdirect('/images/icon_clipboard.png') }}" + alt="Under a GNU LGPL v.3 or Creative Commons BY-SA 3.0 license. + Distributed by the GNOME project http://www.gnome.org" /> + <a href="{{ request.urlgen('mediagoblin.moderation.reports_detail', + report_id=report.id) }}"> + {% trans report_id=report.id %} + Closed Report #{{ report_id }} + {% endtrans %} + </a> + </td> + <td>{{ report.resolved.strftime("%F %R") }}</td> + <td>{{ report.reported_user.username }}</td> + <td>{{ report.created.strftime("%F %R") }}</td> + <td>{{ report.reporter.username }}</td> + <td>{{ report.report_content[:15] }}...</td> + </tr> + {% endfor %} + </table> +{% else %} + <p><em>{% trans %}No closed reports found.{% endtrans %}</em></p> +{% endif %} + +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/moderation/user.html b/mediagoblin/templates/mediagoblin/moderation/user.html new file mode 100644 index 00000000..6335ea12 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/moderation/user.html @@ -0,0 +1,217 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title %} + {%- if user -%} + {%- trans username=user.username -%} + User: {{ username }} + {%- endtrans %} — {{ super() }} + {%- else -%} + {{ super() }} + {%- endif -%} +{% endblock %} + +{%- block mediagoblin_head %} + <script src="{{ request.staticdirect('/js/setup_report_forms.js') }}"> + </script> +{% endblock %} + +{% block mediagoblin_content -%} + {# If no user... #} + {% if not user %} + <p>{% trans %}Sorry, no such user found.{% endtrans %}</p> + {# User exists, but needs verification #} + {% elif not user.has_privilege('active') %} + <div class="profile_sidebar empty_space"> + <h1>{% trans %}Email verification needed{% endtrans %}</h1> + <p> + {% trans -%} + Someone has registered an account with this username, but it still has + to be activated. + {%- endtrans %} + </p> + + </div> + + {# Active(?) (or at least verified at some point) user, horray! #} + {% else %} + <a href="{{ request.urlgen('mediagoblin.moderation.users') }}" + class="return_to_panel button_action" + title="Return to Users Panel"> + {% trans %}Return to Users Panel{% endtrans %}</a> + <h1> + {%- trans username=user.username %}{{ username }}'s profile{% endtrans -%} + {% if user_banned and user_banned.expiration_date %} + — {% trans expiration_date=user_banned.expiration_date -%} + BANNED until {{ expiration_date }} + {%- endtrans %} + {% elif user_banned %} + — {% trans %}Banned Indefinitely{% endtrans %} + {% endif %} + </h1> + {% if not user.url and not user.bio %} + <div class="profile_sidebar empty_space"> + <p> + {% trans -%} + This user hasn't filled in their profile (yet). + {%- endtrans %} + </p> + {% else %} + <div class="profile_sidebar"> + {% include "mediagoblin/utils/profile.html" %} + {% if request.user and + (request.user.id == user.id or request.user.has_privilege('admin')) %} + <a href="{{ request.urlgen('mediagoblin.edit.profile', + user=user.username) }}"> + {%- trans %}Edit profile{% endtrans -%} + </a> + {% endif %} + {% endif %} + <p> + <a href="{{ request.urlgen('mediagoblin.user_pages.collection_list', + user=user.username) }}"> + {%- trans %}Browse collections{% endtrans -%} + </a> + </p> + </div> + {% endif %} + {% if user %} + <h2> + {%- trans username=user.username -%} + Active Reports on {{ username }} + {%- endtrans -%} + </h2> + {% if reports.count() %} + <table class="admin_side_panel"> + <tr> + <th>{%- trans %}Report ID{% endtrans -%}</th> + <th>{%- trans %}Reported Content{% endtrans -%}</th> + <th>{%- trans %}Description of Report{% endtrans -%}</th> + </tr> + {% for report in reports %} + <tr> + <td> + <img src="{{ request.staticdirect('/images/icon_clipboard.png') }}" /> + <a href="{{ request.urlgen('mediagoblin.moderation.reports_detail', + report_id=report.id) }}"> + {%- trans report_number=report.id -%} + Report #{{ report_number }} + {%- endtrans -%} + </a> + </td> + <td> + {% if report.discriminator == "comment_report" %} + <a>{%- trans %}Reported Comment{% endtrans -%}</a> + {% elif report.discriminator == "media_report" %} + <a>{%- trans %}Reported Media Entry{% endtrans -%}</a> + {% endif %} + </td> + <td>{{ report.report_content[:21] }} + {% if report.report_content|count >20 %}...{% endif %}</td> + <td>{%- trans %}Resolve{% endtrans -%}</td> + </tr> + {% endfor %} + <tr><td></td><td></td> + </table> + {% else %} + {%- trans username=user.username -%} + No active reports filed on {{ username }} + {%- endtrans -%} + {% endif %} + <span class="right_align"> + <a href="{{ request.urlgen( + 'mediagoblin.moderation.reports') }}?reported_user={{user.id}}"> + {%- trans + username=user.username %}All reports on {{ username }}{% endtrans %}</a> + · + <a href="{{ request.urlgen( + 'mediagoblin.moderation.reports') }}?reporter={{user.id}}"> + {%- trans username=user.username -%} + All reports that {{ username }} has filed + {%- endtrans %}</a> + </span> + <span class=clear></span> + <h2>{% trans username=user.username -%} + {{ username }}'s Privileges{% endtrans %}</h2> + <form method=POST action="{{ request.urlgen( + 'mediagoblin.moderation.ban_or_unban', + user=user.username) }}" class="right_align"> + {{ csrf_token }} + {% if request.user.has_privilege('admin') and not user_banned and + not user.id == request.user.id %} + {{ wtforms_util.render_divs(ban_form) }} + <input type=submit class="button_action" + value="{% trans %}Ban User{% endtrans %}" + id="ban_user_submit" /> + {% elif request.user.has_privilege('admin') and + not user.id == request.user.id %} + <input type=submit class="button_action right_align" + value="{% trans %}UnBan User{% endtrans %}" /> + {% endif %} + </form> + <form action="{{ request.urlgen('mediagoblin.moderation.give_or_take_away_privilege', + user=user.username) }}" + method=post > + <table class="admin_side_panel"> + <tr> + <th>{% trans %}Privilege{% endtrans %}</th> + <th>{% trans %}User Has Privilege{% endtrans %}</th> + </tr> + {% for privilege in privileges %} + <tr> + <td>{{ privilege.privilege_name }}</td> + {% if privilege in user.all_privileges %} + <td class="user_with_privilege"> + {% trans %}Yes{% endtrans %}{% else %} + <td class="user_without_privilege"> + {% trans %}No{% endtrans %}{% endif %} + </td> + {% if request.user.has_privilege('admin') %} + <td> + {% if privilege in user.all_privileges %} + <input type=submit id="{{ privilege.privilege_name }}" + class="submit_button button_action" + value =" -" /> + {% else %} + <input type=submit id="{{ privilege.privilege_name }}" + class="submit_button button_action" + value ="+" /> + {% endif %} + </td> + {% endif %} + </tr> + {% endfor %} + </table> + {{ csrf_token }} + <input type=hidden name=privilege_name id=hidden_privilege_name /> + </form> + {% endif %} + <script> +$(document).ready(function(){ + $('.submit_button').click(function(){ + $('#hidden_privilege_name').val($(this).attr('id')); + }); + init_user_banned_form(); + $('#ban_user_submit').click(function(){ + submit_user_banned_form() + }); +}); + </script> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/moderation/user_panel.html b/mediagoblin/templates/mediagoblin/moderation/user_panel.html new file mode 100644 index 00000000..4949960e --- /dev/null +++ b/mediagoblin/templates/mediagoblin/moderation/user_panel.html @@ -0,0 +1,97 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% block title -%} + {% trans %}User panel{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} + +<h1>{% trans %}User panel{% endtrans %}</h1> + +<p> + {% trans %} + Here you can look up users in order to take punitive actions on them. + {% endtrans %} +</p> + +<h2>{% trans %}Active Users{% endtrans %}</h2> + +{% if user_list.count() %} + {% if not last_page == 1 %} + {% if 'p='~current_page in request.query_string %} + {% set query_string = request.query_string %}{% else %} + {% set query_string = +'p='~current_page~"&"+request.query_string %} + {% endif %} + <div class="right_align"> + {% set first_vis = current_page-3 %} + {% set last_vis = current_page+3 %} + {% if 1 == current_page %}<b>1</b>{% else %} + <a href ="?{{ query_string.replace( + 'p='~current_page, + 'p='~1) }}"> + 1</a>{% endif %} + {% if first_vis > 1 %}...{% endif %} + {% for p in range(first_vis,last_vis+1) %} + {% if p > 1 and p < last_page and +current_page !=p %} + <a href="?{{ query_string.replace( + 'p='~current_page, + 'p='~p) }}"> + {{ p }}</a> + {% elif p > 1 and p < last_page %} + <b>{{ p }}</b> + {% endif %} + {% endfor %} + {% if last_vis < last_page %}...{% endif %} + {% if last_page != current_page %} + <a href ="?{{ query_string.replace( + 'p='~current_page, + 'p='~last_page) }}"> + {{ last_page }}</a> + {% else %}<b>{{ last_page }}</b> + {% endif %} + </div> + {% endif %} + <table class="admin_panel processing"> + <tr> + <th>{% trans %}ID{% endtrans %}</th> + <th>{% trans %}Username{% endtrans %}</th> + <th>{% trans %}When Joined{% endtrans %}</th> + <th>{% trans %}# of Comments Posted{% endtrans %}</th> + </tr> + {% for user in user_list %} + <tr> + <td>{{ user.id }}</td> + <td> + <a href="{{ request.urlgen('mediagoblin.moderation.users_detail', + user= user.username) }}"> + {{ user.username }} + </a> + </td> + <td>{{ user.created.strftime("%F %R") }}</td> + <td>{{ user.posted_comments.count() }}</td> + </tr> + {% endfor %} + </table> +{% else %} + <p><em>{% trans %}No users found.{% endtrans %}</em></p> +{% endif %} +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html index 529d89ef..15d53af1 100644 --- a/mediagoblin/templates/mediagoblin/root.html +++ b/mediagoblin/templates/mediagoblin/root.html @@ -27,23 +27,8 @@ {%- endblock mediagoblin_head %} {% block mediagoblin_content %} - {% if request.user %} - <h1>{% trans %}Explore{% endtrans %}</h1> - {% else %} - <h1>{% trans %}Hi there, welcome to this MediaGoblin site!{% endtrans %}</h1> - <img class="right_align" src="{{ request.staticdirect('/images/frontpage_image.png') }}" /> - <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, and more, you can log in with your MediaGoblin account.{% endtrans %}</p> - {% if allow_registration %} - <p>{% trans %}Don't have one yet? It's easy!{% endtrans %}</p> - {% trans register_url=request.urlgen('mediagoblin.auth.register') -%} - <a class="button_action_highlight" href="{{ register_url }}">Create an account at this site</a> - or - <a class="button_action" href="http://wiki.mediagoblin.org/HackingHowto">Set up MediaGoblin on your own server</a> - {%- endtrans %} - {% endif %} - <div class="clear"></div> - {% endif %} + {% include "mediagoblin/bits/frontpage_welcome.html" %} + <h2>{% trans %}Most recent media{% endtrans %}</h2> {{ object_gallery(request, media_entries, pagination) }} diff --git a/mediagoblin/templates/mediagoblin/submit/start.html b/mediagoblin/templates/mediagoblin/submit/start.html index aa390f56..d335d742 100644 --- a/mediagoblin/templates/mediagoblin/submit/start.html +++ b/mediagoblin/templates/mediagoblin/submit/start.html @@ -19,6 +19,11 @@ {% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} +{% block mediagoblin_head %} + <script type="text/javascript" + src="{{ request.staticdirect('/js/file_size.js') }}"></script> +{% endblock %} + {% block title -%} {% trans %}Add your media{% endtrans %} — {{ super() }} {%- endblock %} diff --git a/mediagoblin/templates/mediagoblin/terms_of_service.html b/mediagoblin/templates/mediagoblin/terms_of_service.html new file mode 100644 index 00000000..610afd25 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/terms_of_service.html @@ -0,0 +1,303 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{% extends "mediagoblin/base.html" %} + +{% block title %} + Terms of Service +{% endblock %} + +{% block mediagoblin_content -%} +{# <h2>The gist</h2> +# This is where you might insert your own particular rules, unique to your +# own website. Or your own worded summary. +#} + +<h2>Terms of Service</h2> + +<p> +The following terms and conditions govern all use of the +{{ app_config['html_title'] }} website and all content, services and products +available at or through the website (taken together, the Website). +"Operator" means the owners and operators of this website. +The Website is offered subject to your acceptance without modification of all +of the terms and conditions contained herein and all other operating rules, +policies (including, without limitation, Operator’s Privacy Policy) and +procedures that may be published from time to time on this Site by Operator +(collectively, the “Agreementâ€). +</p> + +<p> +Please read this Agreement carefully before accessing or using the Website. +By accessing or using any part of the web site, you agree to become bound by +the terms and conditions of this agreement. If you do not agree to all the +terms and conditions of this agreement, then you may not access the Website +or use any services. If these terms and conditions are considered an offer by +Operator, acceptance is expressly limited to these terms. The Website is +available only to individuals who are at least 13 years old. +</p> + +<ol id="code_of_conduct_list"> + <li><strong>Your {{ app_config['html_title'] }} Account and Site.</strong> + If you create a notice stream on the Website, you are responsible for + maintaining the security of your account and notice stream, and you are + fully responsible for all activities that occur under the account and any + other actions taken in connection with the notice stream. You must not + describe or assign keywords to your notice stream in a misleading or + unlawful manner, + including in a manner intended to trade on the name or reputation of + others, and Operator may change or remove any description or keyword that + it considers inappropriate or unlawful, or otherwise likely to cause + Operator liability. You must immediately notify Operator of any + unauthorized uses of your notice stream, your account or any other breaches + of security. Operator will not be liable for any acts or omissions by You, + including any damages of any kind incurred as a result of such acts or + omissions. + </li> + <li><strong>Responsibility of Contributors.</strong> If you operate a notice + stream, comment on a notice stream, post material to the Website, post + links on the Website, or otherwise make + (or allow any third party to make) material + available by means of the Website (any such material, “Contentâ€), You are + entirely responsible for the content of, and any harm resulting from, that + Content. That is the case regardless of whether the Content in question + constitutes text, graphics, an audio file, or computer software. By making + Content available, you represent and warrant that: + <ul class="nested_sublist"> + <li> + the downloading, copying and use of the Content will not infringe + the proprietary rights, including but not limited to the copyright, + patent, trademark or trade secret rights, of any third party; + </li> + <li> + if your employer has rights to any copyrights, patents, or trademarks + you create, you have either (i) received permission from your employer + to post or make available the Content, including but not limited to any + software, or (ii) secured from your employer a waiver as to all rights + in or to the Content; + </li> + <li> + you have fully complied with any third-party licenses relating to the + Content, and have done all things necessary to successfully pass + through to end users any required terms; + </li> + <li>the Content does not contain or install any viruses, worms, malware, + Trojan horses or other harmful or destructive content; + </li> + <li>the Content is not spam, and does not contain unethical or unwanted + commercial content designed to drive traffic to third party sites or + boost the search engine rankings of third party sites, or to further + unlawful acts (such as phishing) or mislead recipients as to the + source of the material (such as spoofing); + </li> + <li>if the Content is machine- or randomly-generated, it is for purposes + of direct entertainment, information and/or utility for you or other + users, and not for spam, + </li> + <li>the Content is not libelous or defamatory (more info on what that + means), does not contain threats or incite violence towards individuals + or entities, and does not violate the privacy or publicity rights of + any third party; + </li> + <li>your notice stream is not getting advertised via unwanted electronic + messages such as spam links on newsgroups, email lists, other notice + streams and web sites, and similar unsolicited promotional methods; + </li> + <li>your notice stream is not named in a manner that misleads your + readers into thinking that you are another person or company. For + example, your notice stream’s URL or name is not the name of a person + other than yourself or company other than your own; and + </li> + <li>you have, in the case of Content that includes computer code, + accurately categorized and/or described the type, nature, uses and + effects of the materials, whether requested to do so by Operator or + otherwise.</li> + </ul> + By submitting Content to Operator for inclusion on your Website, you grant + Operator a world-wide, royalty-free, and non-exclusive license to + reproduce, modify, adapt and publish the Content solely for the purpose of + displaying, distributing and promoting your notice stream. + By submitting Content to Operator for inclusion on your Website, you grant + all readers the right to use, re-use, modify and/or re-distribute the + Content under the terms of the Creative Commons Attribution 3.0. + If you delete Content, Operator will use reasonable efforts to remove it + from the Website, but you acknowledge that caching or references to the + Content may not be made immediately unavailable. + Without limiting any of those representations or warranties, Operator has + the right (though not the obligation) to, in Operator’s sole discretion + (i) refuse or remove any content that, in Operator’s reasonable opinion, + violates any Operator policy or is in any way harmful or objectionable, or + (ii) terminate or deny access to and use of the Website to any individual + or entity for any reason, in Operator’s sole discretion. + </li> + <li><strong>Responsibility of Website Visitors.</strong> Operator has not + reviewed, and cannot + review, all of the material, including computer software, posted to the + Website, and cannot therefore be responsible for that material’s content, + use or effects. By operating the Website, Operator does not represent or + imply that it endorses the material there posted, or that it believes such + material to be accurate, useful or non-harmful. You are responsible for + taking precautions as necessary to protect yourself and your computer + systems from viruses, worms, Trojan horses, and other harmful or + destructive content. The Website may contain content that is offensive, + indecent, or otherwise objectionable, as well as content containing + technical inaccuracies, typographical mistakes, and other errors. The + Website may also contain material that violates the privacy or publicity + rights, or infringes the copyright, patent, trademark and other proprietary + rights, of third parties, or the downloading, copying or use of which is + subject to additional terms and conditions, stated or unstated. Operator + disclaims any responsibility for any harm resulting from the use by + visitors of the Website, or from any downloading by those visitors of + content there posted. + </li> + <li><strong>Content Posted on Other Websites.</strong> We have not reviewed, + and cannot + review, all of the material, including computer software, made available + through the websites and webpages to which {{ app_config['html_title'] }} + links, and that link to {{ app_config['html_title'] }}. Operator does not + have any control over those external websites and webpages, and is not + responsible for their contents or their use. By linking to a external + website or webpage, Operator does not represent or imply that it endorses + such website or webpage. You are responsible for taking precautions as + necessary to protect yourself and your computer systems from viruses, + worms, Trojan horses, and other harmful or destructive content. Operator + disclaims any responsibility for any harm resulting from your use of + external websites and webpages. + </li> + <li> + <strong>Copyright Infringement and DMCA Policy.</strong> + As Operator asks others to respect its copyrights and trademark rights, + it respects the copyright, patent, and trademark rights of others. + If you believe that material located on or linked to by + {{ app_config['html_title'] }} violates your copyright, you are encouraged + to notify Operator in accordance with Operator’s Digital Millennium + Copyright Act (â€DMCAâ€) Policy. Operator will respond to all such notices, + including as required or appropriate by removing the infringing material or + disabling all links to the infringing material. In the case of a visitor who + may infringe or repeatedly infringes the copyrights or other trademark or + patent rights of Operator or others, Operator may, in its discretion, + terminate or deny access to and use of the Website. In the case of such + termination, Operator will have no obligation to provide a refund of any + amounts previously paid to Operator.</li> + <li> + <strong>Copyrights, patents, and trademarks.</strong> + This Agreement does not transfer from Operator to + you any Operator or third party copyrights, patents, or trademarks, + and all right, title and interest in and to such copyrights, patents, + and trademarks will remain (as between the + parties) solely with Operator. {{ app_config['html_title'] }}, the + {{ app_config['html_title'] }} logo, and all other trademarks, service + marks, graphics and logos used in connection with + {{ app_config['html_title'] }}, or the Website may be trademarks or + registered trademarks of Operator or Operator’s licensors. Other + trademarks, service marks, graphics and logos used in connection with the + Website may be the trademarks of other third parties. Your use of the + Website grants you no right or license to reproduce or otherwise use any + Operator or third-party trademarks. + </li> + <li><strong>Changes.</strong> Operator reserves the right, at its sole + discretion, to modify + or replace any part of this Agreement. It is your responsibility to check + this Agreement periodically for changes. Your continued use of or access + to the Website following the posting of any changes to this Agreement + constitutes acceptance of those changes. Operator may also, in the future, + offer new services and/or features through the Website (including, the + release of new tools and resources). Such new features and/or services + shall be subject to the terms and conditions of this Agreement. + </li> + <li><strong>Termination.</strong> Operator may terminate your access to all + or any part of + the Website at any time, with or without cause, with or without notice, + effective immediately. If you wish to terminate this Agreement or your + {{ app_config['html_title'] }} account (if you have one), you may simply + discontinue using the Website. All provisions of this Agreement which by + their nature should survive termination shall survive termination, + including, without limitation, ownership provisions, warranty disclaimers, + indemnity and limitations of liability. + </li> + <li><strong>Disclaimer of Warranties.</strong> The Website is provided + “as isâ€. Operator and + its suppliers and licensors hereby disclaim all warranties of any kind, + express or implied, including, without limitation, the warranties of + merchantability, fitness for a particular purpose and non-infringement. + Neither Operator nor its suppliers and licensors, makes any warranty that + the Website will be error free or that access thereto will be continuous + or uninterrupted. If you’re actually reading this, here’s a treat. You + understand that you download from, or otherwise obtain content or services + through, the Website at your own discretion and risk. + </li> + <li><strong>Limitation of Liability.</strong> In no event will Operator, or + its suppliers or + licensors, be liable with respect to any subject matter of this agreement + under any contract, negligence, strict liability or other legal or + equitable theory for: (i) any special, incidental or consequential damages; + (ii) the cost of procurement or substitute products or services; (iii) for + interruption of use or loss or corruption of data; or (iv) for any amounts + that exceed the fees paid by you to Operator under this agreement during + the twelve (12) month period prior to the cause of action. Operator shall + have no liability for any failure or delay due to matters beyond their + reasonable control. The foregoing shall not apply to the extent prohibited + by applicable law. + </li> + <li><strong>General Representation and Warranty.</strong> You represent and + warrant that (i) + your use of the Website will be in strict accordance with the Operator + Privacy Policy, with this Agreement and with all applicable laws and + regulations (including without limitation any local laws or regulations in + your country, state, city, or other governmental area, regarding online + conduct and acceptable content, and including all applicable laws regarding + the transmission of technical data exported from the United States or the + country in which you reside) and (ii) your use of the Website will not + infringe or misappropriate the copyrights, patents, and trademark rights of + any third party. + </li> + <li> + <strong>Indemnification.</strong> + You agree to indemnify and hold harmless Operator, its contractors, and its + licensors, and their respective directors, officers, employees and agents + from and against any and all claims and expenses, including attorneys’ fees, + arising out of your use of the Website, including but not limited to out of + your violation this Agreement. + </li> + <li><strong>Miscellaneous.</strong> This Agreement constitutes the entire + agreement between + Operator and you concerning the subject matter hereof, and they may only + be modified by a written amendment signed by an authorized executive of + Operator, or by the posting by Operator of a revised version. If any part + of this Agreement is held invalid or unenforceable, that part will be + construed to reflect the parties’ original intent, and the remaining + portions will remain in full force and effect. A waiver by either party of + any term or condition of this Agreement or any breach thereof, in any one + instance, will not waive such term or condition or any subsequent breach + thereof. You may assign your rights under this Agreement to any party that + consents to, and agrees to be bound by, its terms and conditions; Operator + may assign its rights under this Agreement without condition. This + Agreement will be binding upon and will inure to the benefit of the + parties, their successors and permitted assigns. + </li> +</ol> + +<p> +Originally published by Automattic, Inc. as the WordPress.com Terms of Service +and made available by them under the Creative Commons Attribution- +ShareAlike 3.0 License. Modifications to remove reference to "VIP services", +rename "blog" to "notice stream", remove the choice-of-venue clause, and add +variables specific to instances of this software made by Control Yourself, Inc. +and made available under the terms of the same license. +</p> + +{% endblock -%} diff --git a/mediagoblin/templates/mediagoblin/user_pages/blog_media.html b/mediagoblin/templates/mediagoblin/user_pages/blog_media.html new file mode 100644 index 00000000..c6eedee0 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/user_pages/blog_media.html @@ -0,0 +1,176 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{%- extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} +{% from "mediagoblin/utils/pagination.html" import render_pagination %} + +{% block title %}{{ media.title }} — {{ super() }}{% endblock %} + +{% block mediagoblin_head %} +<!--[if lte IE 8]><link rel="stylesheet" + href="{{ request.staticdirect('/extlib/leaflet/leaflet.ie.css') }}" /><![endif]--> + <script type="text/javascript" + src="{{ request.staticdirect('/js/comment_show.js') }}"></script> + <script type="text/javascript" + src="{{ request.staticdirect('/js/keyboard_navigation.js') }}"></script> + + {% template_hook("media_head") %} +{% endblock mediagoblin_head %} + +{% block mediagoblin_content %} + <p class="context"> + {%- trans user_url=request.urlgen( + 'mediagoblin.user_pages.user_home', + user=media.get_uploader.username), + username=media.get_uploader.username -%} + â– Blog post by <a href="{{user_url}}">{{username}}</a> + {%- endtrans -%} + </p> + {% include "mediagoblin/utils/prev_next.html" %} + <div class="media_pane"> + <div class="media_image_container"> + {% block mediagoblin_media %} + {% set display_media = request.app.public_store.file_url( + media.get_display_media()[1]) %} + {# 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="{% trans media_title=media.title -%} + Image for {{ media_title }}{% endtrans %}" /> + </a> + {% else %} + <img class="media_image" + src="{{ display_media }}" + alt="{% trans media_title=media.title -%} + Image for {{ media_title }}{% endtrans %}" /> + {% endif %} + {% endblock %} + </div> + {% if request.user and + (media.uploader == request.user.id or + request.user.has_privilege('admin')) %} + {% set edit_url = request.urlgen('mediagoblin.media_types.blog.blogpost.edit', + blog_slug=media.media_manager.get_blog_by_blogpost().slug, + user=request.user.username, blog_post_slug=media.slug) %} + <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_id=media.id) %} + <a class="button_action" href="{{ delete_url }}">{% trans %}Delete{% endtrans %}</a> + + {% endif %} + </br> + </br> + {% if comments %} + {% if app_config['allow_comments'] %} + <a + {% if not request.user %} + href="{{ request.urlgen('mediagoblin.auth.login') }}" + {% endif %} + class="button_action" id="button_addcomment" title="Add a comment"> + {% trans %}Add a comment{% endtrans %} + </a> + {% include "mediagoblin/utils/comment-subscription.html" %} + + {% endif %} + {% if request.user %} + <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', + user= media.get_uploader.username, + media_id=media.id) }}" method="POST" id="form_comment"> + {{ 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 %} + <ul style="list-style:none"> + {% for comment in comments %} + {% set comment_author = comment.get_author %} + <li id="comment-{{ comment.id }}" + {%- if pagination.active_id == comment.id %} + class="comment_wrapper comment_active"> + <a name="comment" id="comment"></a> + {%- else %} + class="comment_wrapper"> + {%- endif %} + <div class="comment_author"> + <img src="{{ request.staticdirect('/images/icon_comment.png') }}" /> + <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', + user=comment_author.username) }}" + class="comment_authorlink"> + {{- comment_author.username -}} + </a> + <a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment', + comment=comment.id, + user=media.get_uploader.username, + media=media.slug_or_id) }}#comment" + class="comment_whenlink"> + <span title='{{- comment.created.strftime("%I:%M%p %Y-%m-%d") -}}'> + {%- trans formatted_time=timesince(comment.created) -%} + {{ formatted_time }} ago + {%- endtrans -%} + </span></a>: + </div> + <div class="comment_content"> + {% autoescape False -%} + {{ comment.content_html }} + {%- endautoescape %} + </div> + </li> + {% endfor %} + </ul> + {{ render_pagination(request, pagination, + media.url_for_self(request.urlgen)) }} + {% endif %} + </div> + <div class="media_sidebar"> + <h3>{% trans %}Added{% endtrans %}</h3> + <p><span title="{{ media.created.strftime("%I:%M%p %Y-%m-%d") }}"> + {%- trans formatted_time=timesince(media.created) -%} + {{ formatted_time }} ago + {%- endtrans -%} + </span></p> + + {% block mediagoblin_after_added_sidebar %} + {% endblock %} + + {% if media.tags %} + {% include "mediagoblin/utils/tags.html" %} + {% endif %} + + {% include "mediagoblin/utils/collections.html" %} + + {% include "mediagoblin/utils/license.html" %} + + {% include "mediagoblin/utils/exif.html" %} + + {% template_hook("media_sideinfo") %} + + {% block mediagoblin_sidebar %} + {% endblock %} + + </div> + <div class="clear"></div> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection.html b/mediagoblin/templates/mediagoblin/user_pages/collection.html index 5a7baadd..0f712c01 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/collection.html +++ b/mediagoblin/templates/mediagoblin/user_pages/collection.html @@ -44,8 +44,8 @@ {{ collection_title }} by <a href="{{ user_url }}">{{ username }}</a> {%- endtrans %} </h1> - {% if request.user and (collection.creator == request.user.id or - request.user.is_admin) %} + {% if request.user and (collection.creator == request.user.id or + request.user.has_privilege('admin')) %} {% set edit_url = request.urlgen('mediagoblin.edit.edit_collection', user=collection.get_creator.username, collection=collection.slug) %} @@ -63,10 +63,10 @@ </p> {{ collection_gallery(request, collection_items, pagination) }} - + {% set feed_url = request.urlgen('mediagoblin.user_pages.collection_atom_feed', - user=user.username, + user=user.username, collection=collection.slug ) %} {% include "mediagoblin/utils/feed_link.html" %} - -{% endblock %} + +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html b/mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html index 2b790584..694eb979 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html +++ b/mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html @@ -41,9 +41,10 @@ <div class="form_submit_buttons"> {# TODO: This isn't a button really... might do unexpected things :) #} - <a class="button_action" href="{{ request.urlgen('mediagoblin.user_pages.user_collection', - collection=collection.slug, - user=request.user.username) }}">{% trans %}Cancel{% endtrans %}</a> + <a class="button_action" href=" + {{- collection.url_for_self(request.urlgen) }}"> + {%- trans %}Cancel{% endtrans -%} + </a> <input type="submit" value="{% trans %}Delete permanently{% endtrans %}" class="button_form" /> {{ csrf_token }} </div> diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html b/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html index 449cc3ce..dc31d90f 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html +++ b/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html @@ -47,9 +47,10 @@ <div class="form_submit_buttons"> {# TODO: This isn't a button really... might do unexpected things :) #} - <a class="button_action" href="{{ request.urlgen('mediagoblin.user_pages.user_collection', - collection=collection_item.in_collection.slug, - user=request.user.username) }}">{% trans %}Cancel{% endtrans %}</a> + <a class="button_action" href=" + {{- collection_item.in_collection.url_for_self(request.urlgen) }}"> + {%- trans %}Cancel{% endtrans -%} + </a> <input type="submit" value="{% trans %}Remove{% endtrans %}" class="button_form" /> {{ csrf_token }} </div> diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection_list.html b/mediagoblin/templates/mediagoblin/user_pages/collection_list.html index abf22623..4b449c76 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/collection_list.html +++ b/mediagoblin/templates/mediagoblin/user_pages/collection_list.html @@ -15,7 +15,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. #} -{% extends "mediagoblin/base.html" %} +{%- extends "mediagoblin/base.html" %} {% block title %} {%- trans username=user.username -%} @@ -34,22 +34,22 @@ </h1> {% if request.user %} - {% if request.user.status == 'active' %} + {% if request.user.has_privilege('active') %} <p> <a href="{{ request.urlgen('mediagoblin.submit.collection', user=user.username) }}"> {%- trans %}Create new collection{% endtrans -%} + </a> </p> {% endif %} {% endif %} <ul> {% for coll in collections %} - {% set coll_url = request.urlgen( - 'mediagoblin.user_pages.user_collection', - user=user.username, - collection=coll.slug) %} - <li><a href="{{ coll_url }}">{{ coll.title }}</li> + {%- set coll_url = coll.url_for_self(request.urlgen) %} + <li> + <a href="{{ coll_url }}">{{ coll.title }}</a> + </li> {% endfor %} </ul> diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 7dea3f09..81e5013e 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -43,7 +43,7 @@ {%- endtrans -%} </p> {% include "mediagoblin/utils/prev_next.html" %} - <div class="media_pane"> + <div class="media_pane"> <div class="media_image_container"> {% block mediagoblin_media %} {% set display_media = request.app.public_store.file_url( @@ -71,8 +71,8 @@ {{ media.title }} </h2> {% if request.user and - (media.uploader == request.user.id or - request.user.is_admin) %} + (media.uploader == request.user.id or + request.user.has_privilege('admin')) %} {% set edit_url = request.urlgen('mediagoblin.edit.edit_media', user= media.get_uploader.username, media_id=media.id) %} @@ -81,20 +81,26 @@ user= media.get_uploader.username, media_id=media.id) %} <a class="button_action" href="{{ delete_url }}">{% trans %}Delete{% endtrans %}</a> + {% endif %} {% autoescape False %} <p>{{ media.description_html }}</p> {% endautoescape %} - {% if comments %} - <a - {% if not request.user %} - href="{{ request.urlgen('mediagoblin.auth.login') }}" - {% endif %} - class="button_action" id="button_addcomment" title="Add a comment"> - {% trans %}Add a comment{% endtrans %} - </a> + {% if comments and request.user and request.user.has_privilege('commenter') %} + {% if app_config['allow_comments'] %} + <a + {% if not request.user %} + href="{{ request.urlgen('mediagoblin.auth.login') }}?next={{ + request.base_url|urlencode }}" + {% endif %} + class="button_action" id="button_addcomment" title="Add a comment"> + {% trans %}Add a comment{% endtrans %} + </a> + {% include "mediagoblin/utils/comment-subscription.html" %} + + {% endif %} {% if request.user %} - <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', + <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', user= media.get_uploader.username, media_id=media.id) }}" method="POST" id="form_comment"> {{ wtforms_util.render_divs(comment_form) }} @@ -102,7 +108,10 @@ <input type="submit" value="{% trans %}Add this comment{% endtrans %}" class="button_action" /> {{ csrf_token }} </div> + <input type="hidden" value="{{ request.urlgen('mediagoblin.user_pages.media_preview_comment') }}" id="previewURL" /> + <input type="hidden" value="{% trans %}Comment Preview{% endtrans %}" id="previewText"/> </form> + <div id="comment_preview"></div> {% endif %} <ul style="list-style:none"> {% for comment in comments %} @@ -137,6 +146,15 @@ {{ comment.content_html }} {%- endautoescape %} </div> + <div> + {% if app_config.allow_reporting %} + <a href="{{ request.urlgen('mediagoblin.user_pages.media_home.report_comment', + user=media.get_uploader.username, + media=media.slug_or_id, + comment=comment.id) }}"> + {% trans %}Report{% endtrans %}</a> + {% endif %} + </div> </li> {% endfor %} </ul> @@ -145,22 +163,30 @@ {% endif %} </div> <div class="media_sidebar"> - <h3>Added</h3> + <h3>{% trans %}Added{% endtrans %}</h3> <p><span title="{{ media.created.strftime("%I:%M%p %Y-%m-%d") }}"> - {%- trans formatted_time=timesince(media.created) -%} + {%- trans formatted_time=timesince(media.created) -%} {{ formatted_time }} ago {%- endtrans -%} </span></p> + + {% block mediagoblin_after_added_sidebar %} + {% endblock %} + {% if media.tags %} {% include "mediagoblin/utils/tags.html" %} {% endif %} {% include "mediagoblin/utils/collections.html" %} + {% if app_config.allow_reporting %} + {% include "mediagoblin/utils/report.html" %} + {% endif %} + {% include "mediagoblin/utils/license.html" %} {% include "mediagoblin/utils/exif.html" %} - + {%- if media.attachment_files|count %} <h3>{% trans %}Attachments{% endtrans %}</h3> <ul> @@ -176,7 +202,7 @@ {%- if app_config['allow_attachments'] and request.user and (media.uploader == request.user.id - or request.user.is_admin) %} + or request.user.has_privilege('admin')) %} {%- if not media.attachment_files|count %} <h3>{% trans %}Attachments{% endtrans %}</h3> {%- endif %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/report.html b/mediagoblin/templates/mediagoblin/user_pages/report.html new file mode 100644 index 00000000..ce0fb1bc --- /dev/null +++ b/mediagoblin/templates/mediagoblin/user_pages/report.html @@ -0,0 +1,83 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{%- extends "mediagoblin/base.html" %} +{%- import "/mediagoblin/utils/wtforms.html" as wtforms_util %} +{%- block mediagoblin_content -%} +{% trans %}<h2>File a Report</h2>{% endtrans %} +<form action="" method=POST > + {% if comment is defined %} + <h3>{% trans %}Reporting this Comment{% endtrans %}</h3> + {%- set comment_author = comment.get_author %} + {%- set comment_author_url = request.urlgen( + 'mediagoblin.user_pages.user_home', + user=comment_author.username) %} + {%- set comment_url = request.urlgen( + 'mediagoblin.user_pages.media_home.view_comment', + comment=comment.id, + user=media.get_uploader.username, + media=media.slug_or_id) %} + <div id="comment-{{ comment.id }}" + class="comment_wrapper"> + <div class="comment_author"> + <img + src="{{ request.staticdirect('/images/icon_comment.png') }}" /> + <a href="{{ comment_author_url }}" + class="comment_authorlink"> + {{- comment_author.username -}} + </a> + <a href="{{ comment_url }}" + class="comment_whenlink"> + <span + title='{{- comment.created.strftime("%I:%M%p %Y-%m-%d") -}}'> + + {%- trans formatted_time=timesince(comment.created) -%} + {{ formatted_time }} ago + {%- endtrans -%} + </span></a>: + </div> + <div class="comment_content"> + {% autoescape False -%} + {{ comment.content_html }} + {%- endautoescape %} + </div> + </div> + {% elif media is defined %} + <h3>{% trans %}Reporting this Media Entry{% endtrans %}</h3> + <div class="media_thumbnail"> + <a href="{{ request.urlgen('mediagoblin.user_pages.media_home', + user=media.get_uploader.username, + media=media.slug_or_id) }}"> + <img src="{{ media.thumb_url }}"/></a> + <a href="{{ request.urlgen('mediagoblin.user_pages.media_home', + user=media.get_uploader.username, + media=media.slug_or_id) }}" + class=thumb_entry_title>{{ media.title }}</a> + </div> + <div class=clear></div> + {%- trans user_url = request.urlgen('mediagoblin.user_pages.user_home', user=media.get_uploader.username), + username = media.get_uploader.username %} + â– Published by <a href="{{ user_url }}" + class="comment_authorlink">{{ username }}</a> + {% endtrans %} + {%- endif %} + + {{- wtforms_util.render_divs(form) }} + {{ csrf_token }} + <input type=submit value="{% trans %}File Report {% endtrans %}" /> +</form> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html index 71acd66c..14a67431 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/user.html +++ b/mediagoblin/templates/mediagoblin/user_pages/user.html @@ -14,6 +14,9 @@ # # 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 is the main user homepage for active users #} {% extends "mediagoblin/base.html" %} @@ -38,134 +41,87 @@ {% block mediagoblin_content -%} - {# If no user... #} - {% if not user %} - <p>{% trans %}Sorry, no such user found.{% endtrans %}</p> - - {# User exists, but needs verification #} - {% elif user.status == "needs_email_verification" %} - {% if user == request.user %} - {# this should only be visible when you are this user #} - <div class="form_box"> - <h1>{% trans %}Email verification needed{% endtrans %}</h1> + <h1> + {%- trans username=user.username %}{{ username }}'s profile{% endtrans -%} + </h1> + {% if not user.url and not user.bio %} + {% if request.user and (request.user.id == user.id) %} + <div class="profile_sidebar empty_space"> <p> - {% trans -%} - Almost done! Your account still needs to be activated. - {%- endtrans %} - </p> - <p> - {% trans -%} - An email should arrive in a few moments with instructions on how to do so. - {%- endtrans %} + {% trans %}Here's a spot to tell others about yourself.{% endtrans %} </p> - <p>{% trans %}In case it doesn't:{% endtrans %}</p> - - <a href="{{ request.urlgen('mediagoblin.auth.resend_verification') }}" - class="button_action_highlight">{% trans %}Resend verification email{% endtrans %}</a> - </div> + <a href="{{ request.urlgen('mediagoblin.edit.profile', + user=user.username) }}" class="button_action"> + {%- trans %}Edit profile{% endtrans -%} + </a> {% else %} - {# if the user is not you, but still needs to verify their email #} - <div class="form_box"> - <h1>{% trans %}Email verification needed{% endtrans %}</h1> - + <div class="profile_sidebar empty_space"> <p> {% trans -%} - Someone has registered an account with this username, but it still has to be activated. - {%- endtrans %} - </p> - - <p> - {% trans login_url=request.urlgen('mediagoblin.auth.login') -%} - If you are that person but you've lost your verification email, you can <a href="{{ login_url }}">log in</a> and resend it. + This user hasn't filled in their profile (yet). {%- endtrans %} </p> - </div> {% endif %} - - {# Active(?) (or at least verified at some point) user, horray! #} {% else %} - <h1> - {%- trans username=user.username %}{{ username }}'s profile{% endtrans -%} - </h1> - - {% if not user.url and not user.bio %} - {% if request.user and (request.user.id == user.id) %} - <div class="profile_sidebar empty_space"> - <p> - {% trans %}Here's a spot to tell others about yourself.{% endtrans %} - </p> - <a href="{{ request.urlgen('mediagoblin.edit.profile', - user=user.username) }}" class="button_action"> - {%- trans %}Edit profile{% endtrans -%} - </a> - {% else %} - <div class="profile_sidebar empty_space"> - <p> - {% trans -%} - This user hasn't filled in their profile (yet). - {%- endtrans %} - </p> + <div class="profile_sidebar"> + {% include "mediagoblin/utils/profile.html" %} + {% if request.user and + (request.user.id == user.id or request.user.has_privilege('admin')) %} + <a href="{{ request.urlgen('mediagoblin.edit.profile', + user=user.username) }}"> + {%- trans %}Edit profile{% endtrans -%} + </a> {% endif %} - {% else %} - <div class="profile_sidebar"> - {% include "mediagoblin/utils/profile.html" %} - {% if request.user and - (request.user.id == user.id or request.user.is_admin) %} - <a href="{{ request.urlgen('mediagoblin.edit.profile', - user=user.username) }}"> - {%- trans %}Edit profile{% endtrans -%} - </a> - {% endif %} - {% endif %} + {% endif %} + <p> + <a href="{{ request.urlgen('mediagoblin.user_pages.collection_list', + user=user.username) }}"> + {%- trans %}Browse collections{% endtrans -%} + </a> + </p> + </div> + + {% if media_entries.count() %} + <div class="profile_showcase"> + {{ object_gallery(request, media_entries, pagination, + pagination_base_url=user_gallery_url, col_number=3) }} + {% include "mediagoblin/utils/object_gallery.html" %} + <div class="clear"></div> <p> - <a href="{{ request.urlgen('mediagoblin.user_pages.collection_list', - user=user.username) }}"> - {%- trans %}Browse collections{% endtrans -%} + <a href="{{ user_gallery_url }}"> + {% trans username=user.username -%} + View all of {{ username }}'s media{% endtrans -%} </a> </p> + {% set feed_url = request.urlgen( + 'mediagoblin.user_pages.atom_feed', + user=user.username) %} + {% include "mediagoblin/utils/feed_link.html" %} </div> - - {% if media_entries.count() %} - <div class="profile_showcase"> - {{ object_gallery(request, media_entries, pagination, - pagination_base_url=user_gallery_url, col_number=3) }} - {% include "mediagoblin/utils/object_gallery.html" %} - <div class="clear"></div> + {% else %} + {% if request.user and (request.user.id == user.id) %} + <div class="profile_showcase empty_space"> <p> - <a href="{{ user_gallery_url }}"> - {% trans username=user.username -%} - View all of {{ username }}'s media{% endtrans -%} - </a> + {% trans -%} + This is where your media will appear, but you don't seem to have added anything yet. + {%- endtrans %} </p> - {% set feed_url = request.urlgen( - 'mediagoblin.user_pages.atom_feed', - user=user.username) %} - {% include "mediagoblin/utils/feed_link.html" %} + <a class="button_action" + href="{{ request.urlgen('mediagoblin.submit.start') }}"> + {%- trans %}Add media{% endtrans -%} + </a> </div> {% else %} - {% if request.user and (request.user.id == user.id) %} - <div class="profile_showcase empty_space"> - <p> - {% trans -%} - This is where your media will appear, but you don't seem to have added anything yet. - {%- endtrans %} - </p> - <a class="button_action" - href="{{ request.urlgen('mediagoblin.submit.start') }}"> - {%- trans %}Add media{% endtrans -%} - </a> - </div> - {% else %} - <div class="profile_showcase empty_space"> - <p> - {% trans -%} - There doesn't seem to be any media here yet... - {%- endtrans %} - </p> - </div> - {% endif %} + <div class="profile_showcase empty_space"> + <p> + {% trans -%} + There doesn't seem to be any media here yet... + {%- endtrans %} + </p> + </div> {% endif %} - <div class="clear"></div> {% endif %} + {% template_hook("user_profile") %} + <div class="clear"></div> {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html b/mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html new file mode 100644 index 00000000..6c9b5b8c --- /dev/null +++ b/mediagoblin/templates/mediagoblin/user_pages/user_nonactive.html @@ -0,0 +1,81 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. + +# This is the main user homepage for non-active users that still need +# registration etc. +#} +{% extends "mediagoblin/base.html" %} + +{% block title %} + {%- if user -%} + {%- trans username=user.username -%} + {{ username }}'s profile + {%- endtrans %} — {{ super() }} + {%- else -%} + {{ super() }} + {%- endif -%} +{% endblock %} + + +{% block mediagoblin_content -%} + {# User exists, but needs verification #} + {% if not user.has_privilege('active') %} + {% if user == request.user %} + {# this should only be visible when you are this user #} + <div class="form_box"> + <h1>{% trans %}Email verification needed{% endtrans %}</h1> + + <p> + {% trans -%} + Almost done! Your account still needs to be activated. + {%- endtrans %} + </p> + <p> + {% trans -%} + An email should arrive in a few moments with instructions on how to do so. + {%- endtrans %} + </p> + <p>{% trans %}In case it doesn't:{% endtrans %}</p> + + <a href="{{ request.urlgen('mediagoblin.auth.resend_verification') }}" + class="button_action_highlight">{% trans %}Resend verification email{% endtrans %}</a> + </div> + {% else %} + {# if the user is not you, but still needs to verify their email #} + <div class="form_box"> + <h1>{% trans %}Email verification needed{% endtrans %}</h1> + + <p> + {% trans -%} + Someone has registered an account with this username, but it still has to be activated. + {%- endtrans %} + </p> + <p> + {% trans login_url=request.urlgen('mediagoblin.auth.login') -%} + If you are that person but you've lost your verification email, you can <a href="{{ login_url }}">log in</a> and resend it. + {%- endtrans %} + </p> + </div> + {% endif %} + + {# Active(?) (or at least verified at some point) user, horray! #} + {% else %} + <h1>{{ username }}</h1> + <p>{{ username }} is not active.</p> + <div class="clear"></div> + {% endif %} +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/utils/collection_gallery.html b/mediagoblin/templates/mediagoblin/utils/collection_gallery.html index dcc59244..dfe2ebe2 100644 --- a/mediagoblin/templates/mediagoblin/utils/collection_gallery.html +++ b/mediagoblin/templates/mediagoblin/utils/collection_gallery.html @@ -38,8 +38,8 @@ <a href="{{ entry_url }}">{{ item.note }}</a> {% endif %} {% if request.user and - (item.in_collection.creator == request.user.id or - request.user.is_admin) %} + (item.in_collection.creator == request.user.id or + request.user.has_privilege('admin')) %} {%- set remove_url=request.urlgen( 'mediagoblin.user_pages.collection_item_confirm_remove', user=item.in_collection.get_creator.username, diff --git a/mediagoblin/templates/mediagoblin/utils/comment-subscription.html b/mediagoblin/templates/mediagoblin/utils/comment-subscription.html new file mode 100644 index 00000000..75da5e89 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/utils/comment-subscription.html @@ -0,0 +1,33 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} +{%- if request.user %} + {% set subscription = get_comment_subscription(request.user.id, media.id) %} + {% if not subscription or not subscription.notify %} + <a type="submit" href="{{ request.urlgen('mediagoblin.notifications.subscribe_comments', + user=media.get_uploader.username, + media=media.slug_or_id)}}" + class="button_action">Subscribe to comments + </a> + {% else %} + <a type="submit" href="{{ request.urlgen('mediagoblin.notifications.silence_comments', + user=media.get_uploader.username, + media=media.slug_or_id)}}" + class="button_action">Silence comments + </a> + {% endif %} +{%- endif %} diff --git a/mediagoblin/templates/mediagoblin/utils/exif.html b/mediagoblin/templates/mediagoblin/utils/exif.html index a89e69c8..b62208e1 100644 --- a/mediagoblin/templates/mediagoblin/utils/exif.html +++ b/mediagoblin/templates/mediagoblin/utils/exif.html @@ -17,18 +17,51 @@ #} {% block exif_content %} +<noscript> + <style type="text/css"> + #exif_additional_info { + display: block; + } + </style> +</noscript> +<div id="exif_content"> {% if app_config['exif_visible'] and media.media_data and media.media_data.exif_all is defined and media.media_data.exif_all %} - <h3>EXIF</h3> - <table> + <h3>Camera Information</h3> + <table id="exif_camera_information"> + <tbody> + {% for label, value in media.exif_display_data_short().iteritems() %} + <tr> + <td class="col1">{{ label }}</td> + <td>{{ value }}</td> + </tr> + {% endfor %} + </tbody> + </table> + <h3 id="exif_additional_info_button" class="button_action"> + Additional Information + </h3> + <div id="exif_additional_info"> + <table class="exif_info"> {% for key, tag in media.exif_display_iter() %} <tr> - <td>{{ key }}</td> + <td class="col1">{{ key }}</td> <td>{{ tag.printable }}</td> </tr> {% endfor %} </table> + </div> {% endif %} +<script type="text/javascript"> +$(document).ready(function(){ + +$("#exif_additional_info_button").click(function(){ + $("#exif_additional_info").slideToggle("slow"); +}); + +}); +</script> +</div> <!-- end exif_content div --> {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/utils/report.html b/mediagoblin/templates/mediagoblin/utils/report.html new file mode 100644 index 00000000..3829de97 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/utils/report.html @@ -0,0 +1,28 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +#} + +{% block report_content -%} + <p> + <a href="{{ request.urlgen('mediagoblin.user_pages.media_home.report_media', + user=media.get_uploader.username, + media=media.slug_or_id) }}" + class="button_action" id="button_reportmedia" title="Report media"> + {% trans %}Report media{% endtrans %} + </a> + </p> +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html index be6976c2..e079274e 100644 --- a/mediagoblin/templates/mediagoblin/utils/wtforms.html +++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html @@ -33,25 +33,37 @@ {%- endmacro %} {# Generically render a field #} -{% macro render_field_div(field) %} - {{- render_label_p(field) }} - <div class="form_field_input"> - {{ field }} - {%- if field.errors -%} - {% for error in field.errors %} - <p class="form_field_error">{{ error }}</p> - {% endfor %} - {%- endif %} - {%- if field.description %} - <p class="form_field_description">{{ field.description|safe }}</p> - {%- endif %} - </div> +{% macro render_field_div(field, autofocus_first=False) %} + {% if field.type == 'BooleanField' %} + {{ render_bool(field) }} + {% else %} + {{- render_label_p(field) }} + <div class="form_field_input"> + {% if autofocus_first %} + {{ field(autofocus=True) }} + {% else %} + {{ field }} + {% endif %} + {%- if field.errors -%} + {% for error in field.errors %} + <p class="form_field_error">{{ error }}</p> + {% endfor %} + {%- endif %} + {%- if field.description %} + <p class="form_field_description">{{ field.description|safe }}</p> + {%- endif %} + </div> + {% endif %} {%- endmacro %} {# Auto-render a form as a series of divs #} -{% macro render_divs(form) -%} +{% macro render_divs(form, autofocus_first=False) -%} {% for field in form %} - {{ render_field_div(field) }} + {% if autofocus_first and loop.first %} + {{ render_field_div(field, True) }} + {% else %} + {{ render_field_div(field) }} + {% endif %} {% endfor %} {%- endmacro %} @@ -74,3 +86,19 @@ </tr> {% endfor %} {%- endmacro %} + +{# Render a boolean field #} +{% macro render_bool(field) %} + <div class="boolean"> + <label for="{{ field.label.field_id }}"> + {{ field }}</input> + {{ field.description|safe }} + </label> + {%- if field.errors -%} + {% for error in field.errors %} + <p class="form_field_error">{{ error }}</p> + {% endfor %} + {% endif %} + </div> +{% endmacro %} + diff --git a/mediagoblin/tests/__init__.py b/mediagoblin/tests/__init__.py index 5a3235c6..cf200791 100644 --- a/mediagoblin/tests/__init__.py +++ b/mediagoblin/tests/__init__.py @@ -14,23 +14,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import os -import shutil - -from mediagoblin import mg_globals -from mediagoblin.tests.tools import ( - TEST_USER_DEV, suicide_if_bad_celery_environ) - def setup_package(): - suicide_if_bad_celery_environ() import warnings from sqlalchemy.exc import SAWarning warnings.simplefilter("error", SAWarning) - - -def teardown_package(): - # Remove and reinstall user_dev directories - if os.path.exists(TEST_USER_DEV): - shutil.rmtree(TEST_USER_DEV) diff --git a/mediagoblin/tests/appconfig_context_modified.ini b/mediagoblin/tests/appconfig_context_modified.ini new file mode 100644 index 00000000..cc6721f5 --- /dev/null +++ b/mediagoblin/tests/appconfig_context_modified.ini @@ -0,0 +1,27 @@ +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true + +#Runs with an in-memory sqlite db for speed. +sql_engine = "sqlite://" +run_migrations = true + +# Celery shouldn't be set up by the application as it's setup via +# mediagoblin.init.celery.from_celery +celery_setup_elsewhere = true + +[storage:publicstore] +base_dir = %(here)s/user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/user_dev/media/queue + +[celery] +CELERY_ALWAYS_EAGER = true +CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db" +BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db" + +[plugins] +[[mediagoblin.tests.testplugins.modify_context]] diff --git a/mediagoblin/tests/appconfig_plugin_specs.ini b/mediagoblin/tests/appconfig_plugin_specs.ini new file mode 100644 index 00000000..5511cd97 --- /dev/null +++ b/mediagoblin/tests/appconfig_plugin_specs.ini @@ -0,0 +1,21 @@ +[mediagoblin] +direct_remote_path = /mgoblin_static/ +email_sender_address = "notice@mediagoblin.example.org" + +## Uncomment and change to your DB's appropiate setting. +## Default is a local sqlite db "mediagoblin.db". +# sql_engine = postgresql:///gmg + +# set to false to enable sending notices +email_debug_mode = true + +# Set to false to disable registrations +allow_registration = true + +[plugins] +[[mediagoblin.tests.testplugins.pluginspec]] +some_string = "not blork" +some_int = "not an int" + +# this one shouldn't have its own config +[[mediagoblin.tests.testplugins.callables1]] diff --git a/mediagoblin/tests/appconfig_static_plugin.ini b/mediagoblin/tests/appconfig_static_plugin.ini new file mode 100644 index 00000000..5ce5c5bd --- /dev/null +++ b/mediagoblin/tests/appconfig_static_plugin.ini @@ -0,0 +1,27 @@ +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true + +#Runs with an in-memory sqlite db for speed. +sql_engine = "sqlite://" +run_migrations = true + +# Celery shouldn't be set up by the application as it's setup via +# mediagoblin.init.celery.from_celery +celery_setup_elsewhere = true + +[storage:publicstore] +base_dir = %(here)s/user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/user_dev/media/queue + +[celery] +CELERY_ALWAYS_EAGER = true +CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db" +BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db" + +[plugins] +[[mediagoblin.tests.testplugins.staticstuff]] diff --git a/mediagoblin/tests/auth_configs/__init__.py b/mediagoblin/tests/auth_configs/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/mediagoblin/tests/auth_configs/__init__.py diff --git a/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini b/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini new file mode 100644 index 00000000..07c69442 --- /dev/null +++ b/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini @@ -0,0 +1,25 @@ +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true + +sql_engine = "sqlite://" +run_migrations = true + +# Celery shouldn't be set up by the application as it's setup via +# mediagoblin.init.celery.from_celery +celery_setup_elsewhere = true + +[storage:publicstore] +base_dir = %(here)s/user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/user_dev/media/queue + +[celery] +CELERY_ALWAYS_EAGER = true +CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db" +BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db" + +[plugins] diff --git a/mediagoblin/tests/auth_configs/ldap_appconfig.ini b/mediagoblin/tests/auth_configs/ldap_appconfig.ini new file mode 100644 index 00000000..9be37e17 --- /dev/null +++ b/mediagoblin/tests/auth_configs/ldap_appconfig.ini @@ -0,0 +1,41 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true + +sql_engine = "sqlite://" +run_migrations = true + +# Celery shouldn't be set up by the application as it's setup via +# mediagoblin.init.celery.from_celery +celery_setup_elsewhere = true + +[storage:publicstore] +base_dir = %(here)s/user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/user_dev/media/queue + +[celery] +CELERY_ALWAYS_EAGER = true +CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db" +BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db" + +[plugins] +[[mediagoblin.plugins.ldap]] diff --git a/mediagoblin/tests/auth_configs/openid_appconfig.ini b/mediagoblin/tests/auth_configs/openid_appconfig.ini new file mode 100644 index 00000000..3433e139 --- /dev/null +++ b/mediagoblin/tests/auth_configs/openid_appconfig.ini @@ -0,0 +1,41 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true + +sql_engine = "sqlite://" +run_migrations = true + +# Celery shouldn't be set up by the application as it's setup via +# mediagoblin.init.celery.from_celery +celery_setup_elsewhere = true + +[storage:publicstore] +base_dir = %(here)s/user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/user_dev/media/queue + +[celery] +CELERY_ALWAYS_EAGER = true +CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db" +BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db" + +[plugins] +[[mediagoblin.plugins.openid]] diff --git a/mediagoblin/tests/auth_configs/persona_appconfig.ini b/mediagoblin/tests/auth_configs/persona_appconfig.ini new file mode 100644 index 00000000..0bd5d634 --- /dev/null +++ b/mediagoblin/tests/auth_configs/persona_appconfig.ini @@ -0,0 +1,42 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true + +# TODO: Switch to using an in-memory database +sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db" + +# Celery shouldn't be set up by the application as it's setup via +# mediagoblin.init.celery.from_celery +celery_setup_elsewhere = true + +[storage:publicstore] +base_dir = %(here)s/user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/user_dev/media/queue + +[celery] +CELERY_ALWAYS_EAGER = true +CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db" +BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db" + +[plugins] +[[mediagoblin.plugins.persona]] + diff --git a/mediagoblin/tests/conftest.py b/mediagoblin/tests/conftest.py index 25f495d6..dbb0aa0a 100644 --- a/mediagoblin/tests/conftest.py +++ b/mediagoblin/tests/conftest.py @@ -1,7 +1,25 @@ -from mediagoblin.tests import tools +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2013 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. import pytest +from mediagoblin.tests import tools +from mediagoblin.tools.testing import _activate_testing + + @pytest.fixture() def test_app(request): """ @@ -13,3 +31,11 @@ def test_app(request): in differently to get_app. """ return tools.get_app(request) + + +@pytest.fixture() +def pt_fixture_enable_testing(): + """ + py.test fixture to enable testing mode in tools. + """ + _activate_testing() diff --git a/mediagoblin/tests/pytest.ini b/mediagoblin/tests/pytest.ini index d4aa2d69..e561c074 100644 --- a/mediagoblin/tests/pytest.ini +++ b/mediagoblin/tests/pytest.ini @@ -1,2 +1,2 @@ [pytest] -usefixtures = tmpdir
\ No newline at end of file +usefixtures = tmpdir pt_fixture_enable_testing diff --git a/mediagoblin/tests/resources.py b/mediagoblin/tests/resources.py index f7b3037d..480f6d9a 100644 --- a/mediagoblin/tests/resources.py +++ b/mediagoblin/tests/resources.py @@ -29,6 +29,8 @@ EVIL_JPG = resource('evil.jpg') EVIL_PNG = resource('evil.png') BIG_BLUE = resource('bigblue.png') GOOD_PDF = resource('good.pdf') +MED_PNG = resource('medium.png') +BIG_PNG = resource('big.png') def resource_exif(f): diff --git a/mediagoblin/tests/test_api.py b/mediagoblin/tests/test_api.py index 89cf1026..4e0cbd8f 100644 --- a/mediagoblin/tests/test_api.py +++ b/mediagoblin/tests/test_api.py @@ -35,7 +35,8 @@ class TestAPI(object): self.db = mg_globals.database self.user_password = u'4cc355_70k3N' - self.user = fixture_add_user(u'joapi', self.user_password) + self.user = fixture_add_user(u'joapi', self.user_password, + privileges=[u'active',u'uploader']) def login(self, test_app): test_app.post( diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index 755727f9..1bbc3d01 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -1,3 +1,4 @@ + # GNU MediaGoblin -- federated, autonomous media hosting # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. # @@ -13,54 +14,15 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. - import urlparse -import datetime +import pkg_resources +import pytest from mediagoblin import mg_globals -from mediagoblin.auth import lib as auth_lib from mediagoblin.db.models import User -from mediagoblin.tests.tools import fixture_add_user +from mediagoblin.tests.tools import get_app, fixture_add_user from mediagoblin.tools import template, mail - - -######################## -# Test bcrypt auth funcs -######################## - -def test_bcrypt_check_password(): - # Check known 'lollerskates' password against check function - assert auth_lib.bcrypt_check_password( - 'lollerskates', - '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO') - - assert not auth_lib.bcrypt_check_password( - 'notthepassword', - '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO') - - # Same thing, but with extra fake salt. - assert not auth_lib.bcrypt_check_password( - 'notthepassword', - '$2a$12$ELVlnw3z1FMu6CEGs/L8XO8vl0BuWSlUHgh0rUrry9DUXGMUNWwl6', - '3><7R45417') - - -def test_bcrypt_gen_password_hash(): - pw = 'youwillneverguessthis' - - # Normal password hash generation, and check on that hash - hashed_pw = auth_lib.bcrypt_gen_password_hash(pw) - assert auth_lib.bcrypt_check_password( - pw, hashed_pw) - assert not auth_lib.bcrypt_check_password( - 'notthepassword', hashed_pw) - - # Same thing, extra salt. - hashed_pw = auth_lib.bcrypt_gen_password_hash(pw, '3><7R45417') - assert auth_lib.bcrypt_check_password( - pw, hashed_pw, '3><7R45417') - assert not auth_lib.bcrypt_check_password( - 'notthepassword', hashed_pw, '3><7R45417') +from mediagoblin.auth import tools as auth_tools def test_register_views(test_app): @@ -122,31 +84,35 @@ def test_register_views(test_app): template.clear_test_template_context() response = test_app.post( '/auth/register/', { - 'username': u'happygirl', - 'password': 'iamsohappy', - 'email': 'happygrrl@example.org'}) + 'username': u'angrygirl', + 'password': 'iamsoangry', + 'email': 'angrygrrl@example.org'}) response.follow() ## Did we redirect to the proper page? Use the right template? - assert urlparse.urlsplit(response.location)[2] == '/u/happygirl/' - assert 'mediagoblin/user_pages/user.html' in template.TEMPLATE_TEST_CONTEXT + assert urlparse.urlsplit(response.location)[2] == '/u/angrygirl/' + assert 'mediagoblin/user_pages/user_nonactive.html' in template.TEMPLATE_TEST_CONTEXT ## Make sure user is in place - new_user = mg_globals.database.User.find_one( - {'username': u'happygirl'}) + new_user = mg_globals.database.User.query.filter_by( + username=u'angrygirl').first() assert new_user - assert new_user.status == u'needs_email_verification' - assert new_user.email_verified == False + ## Make sure that the proper privileges are granted on registration + + assert new_user.has_privilege(u'commenter') + assert new_user.has_privilege(u'uploader') + assert new_user.has_privilege(u'reporter') + assert not new_user.has_privilege(u'active') ## Make sure user is logged in request = template.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/user_pages/user.html']['request'] + 'mediagoblin/user_pages/user_nonactive.html']['request'] assert request.session['user_id'] == unicode(new_user.id) ## Make sure we get email confirmation, and try verifying assert len(mail.EMAIL_TEST_INBOX) == 1 message = mail.EMAIL_TEST_INBOX.pop() - assert message['To'] == 'happygrrl@example.org' + assert message['To'] == 'angrygrrl@example.org' email_context = template.TEMPLATE_TEST_CONTEXT[ 'mediagoblin/auth/verification_email.txt'] assert email_context['verification_url'] in message.get_payload(decode=True) @@ -156,27 +122,20 @@ def test_register_views(test_app): assert path == u'/auth/verify_email/' parsed_get_params = urlparse.parse_qs(get_params) - ### user should have these same parameters - assert parsed_get_params['userid'] == [ - unicode(new_user.id)] - assert parsed_get_params['token'] == [ - new_user.verification_key] - ## Try verifying with bs verification key, shouldn't work template.clear_test_template_context() response = test_app.get( - "/auth/verify_email/?userid=%s&token=total_bs" % unicode( - new_user.id)) + "/auth/verify_email/?token=total_bs") response.follow() - context = template.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/user_pages/user.html'] + + # Correct redirect? + assert urlparse.urlsplit(response.location)[2] == '/' + # assert context['verification_successful'] == True # TODO: Would be good to test messages here when we can do so... - new_user = mg_globals.database.User.find_one( - {'username': u'happygirl'}) + new_user = mg_globals.database.User.query.filter_by( + username=u'angrygirl').first() assert new_user - assert new_user.status == u'needs_email_verification' - assert new_user.email_verified == False ## Verify the email activation works template.clear_test_template_context() @@ -186,11 +145,9 @@ def test_register_views(test_app): 'mediagoblin/user_pages/user.html'] # assert context['verification_successful'] == True # TODO: Would be good to test messages here when we can do so... - new_user = mg_globals.database.User.find_one( - {'username': u'happygirl'}) + new_user = mg_globals.database.User.query.filter_by( + username=u'angrygirl').first() assert new_user - assert new_user.status == u'active' - assert new_user.email_verified == True # Uniqueness checks # ----------------- @@ -198,9 +155,9 @@ def test_register_views(test_app): template.clear_test_template_context() response = test_app.post( '/auth/register/', { - 'username': u'happygirl', - 'password': 'iamsohappy2', - 'email': 'happygrrl2@example.org'}) + 'username': u'angrygirl', + 'password': 'iamsoangry2', + 'email': 'angrygrrl2@example.org'}) context = template.TEMPLATE_TEST_CONTEXT[ 'mediagoblin/auth/register.html'] @@ -215,7 +172,7 @@ def test_register_views(test_app): template.clear_test_template_context() response = test_app.post( '/auth/forgot_password/', - {'username': u'happygirl'}) + {'username': u'angrygirl'}) response.follow() ## Did we redirect to the proper page? Use the right template? @@ -225,55 +182,37 @@ def test_register_views(test_app): ## Make sure link to change password is sent by email assert len(mail.EMAIL_TEST_INBOX) == 1 message = mail.EMAIL_TEST_INBOX.pop() - assert message['To'] == 'happygrrl@example.org' + assert message['To'] == 'angrygrrl@example.org' email_context = template.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/auth/fp_verification_email.txt'] + 'mediagoblin/plugins/basic_auth/fp_verification_email.txt'] #TODO - change the name of verification_url to something forgot-password-ish assert email_context['verification_url'] in message.get_payload(decode=True) path = urlparse.urlsplit(email_context['verification_url'])[2] get_params = urlparse.urlsplit(email_context['verification_url'])[3] - assert path == u'/auth/forgot_password/verify/' parsed_get_params = urlparse.parse_qs(get_params) - - # user should have matching parameters - new_user = mg_globals.database.User.find_one({'username': u'happygirl'}) - assert parsed_get_params['userid'] == [unicode(new_user.id)] - assert parsed_get_params['token'] == [new_user.fp_verification_key] - - ### The forgotten password token should be set to expire in ~ 10 days - # A few ticks have expired so there are only 9 full days left... - assert (new_user.fp_token_expire - datetime.datetime.now()).days == 9 + assert path == u'/auth/forgot_password/verify/' ## 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=404) - assert response.status.split()[0] == u'404' # status="404 NOT FOUND" + "/auth/forgot_password/verify/?token=total_bs") + response.follow() - ## Try using an expired token to change password, shouldn't work - template.clear_test_template_context() - new_user = mg_globals.database.User.find_one({'username': u'happygirl'}) - 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=404) - assert response.status.split()[0] == u'404' # status="404 NOT FOUND" - new_user.fp_token_expire = real_token_expiration - new_user.save() + # Correct redirect? + assert urlparse.urlsplit(response.location)[2] == '/' ## Verify step 1 of password-change works -- can see form to change password template.clear_test_template_context() response = test_app.get("%s?%s" % (path, get_params)) - assert 'mediagoblin/auth/change_fp.html' in template.TEMPLATE_TEST_CONTEXT + assert 'mediagoblin/plugins/basic_auth/change_fp.html' in \ + template.TEMPLATE_TEST_CONTEXT ## Verify step 2.1 of password-change works -- report success to user template.clear_test_template_context() response = test_app.post( '/auth/forgot_password/verify/', { - 'userid': parsed_get_params['userid'], - 'password': 'iamveryveryhappy', + 'password': 'iamveryveryangry', 'token': parsed_get_params['token']}) response.follow() assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT @@ -282,8 +221,8 @@ def test_register_views(test_app): template.clear_test_template_context() response = test_app.post( '/auth/login/', { - 'username': u'happygirl', - 'password': 'iamveryveryhappy'}) + 'username': u'angrygirl', + 'password': 'iamveryveryangry'}) # User should be redirected response.follow() @@ -296,7 +235,8 @@ def test_authentication_views(test_app): Test logging in and logging out """ # Make a new user - test_user = fixture_add_user(active_user=False) + test_user = fixture_add_user() + # Get login # --------- @@ -310,7 +250,6 @@ def test_authentication_views(test_app): context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] form = context['login_form'] assert form.username.errors == [u'This field is required.'] - assert form.password.errors == [u'This field is required.'] # Failed login - blank user # ------------------------- @@ -328,9 +267,7 @@ def test_authentication_views(test_app): response = test_app.post( '/auth/login/', { 'username': u'chris'}) - context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] - form = context['login_form'] - assert form.password.errors == [u'This field is required.'] + assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT # Failed login - bad user # ----------------------- @@ -394,3 +331,47 @@ def test_authentication_views(test_app): 'password': 'toast', 'next' : '/u/chris/'}) assert urlparse.urlsplit(response.location)[2] == '/u/chris/' + +@pytest.fixture() +def authentication_disabled_app(request): + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'mediagoblin.tests.auth_configs', + 'authentication_disabled_appconfig.ini')) + + +def test_authentication_disabled_app(authentication_disabled_app): + # app.auth should = false + assert mg_globals + assert mg_globals.app.auth is False + + # Try to visit register page + template.clear_test_template_context() + response = authentication_disabled_app.get('/auth/register/') + response.follow() + + # Correct redirect? + assert urlparse.urlsplit(response.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT + + # Try to vist login page + template.clear_test_template_context() + response = authentication_disabled_app.get('/auth/login/') + response.follow() + + # Correct redirect? + assert urlparse.urlsplit(response.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT + + ## Test check_login_simple should return None + assert auth_tools.check_login_simple('test', 'simple') is None + + # Try to visit the forgot password page + template.clear_test_template_context() + response = authentication_disabled_app.get('/auth/register/') + response.follow() + + # Correct redirect? + assert urlparse.urlsplit(response.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT diff --git a/mediagoblin/tests/test_basic_auth.py b/mediagoblin/tests/test_basic_auth.py new file mode 100644 index 00000000..828f0515 --- /dev/null +++ b/mediagoblin/tests/test_basic_auth.py @@ -0,0 +1,103 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import urlparse + +from mediagoblin.db.models import User +from mediagoblin.plugins.basic_auth import tools as auth_tools +from mediagoblin.tests.tools import fixture_add_user +from mediagoblin.tools import template +from mediagoblin.tools.testing import _activate_testing + +_activate_testing() + + +######################## +# Test bcrypt auth funcs +######################## + + +def test_bcrypt_check_password(): + # Check known 'lollerskates' password against check function + assert auth_tools.bcrypt_check_password( + 'lollerskates', + '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO') + + assert not auth_tools.bcrypt_check_password( + 'notthepassword', + '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO') + + # Same thing, but with extra fake salt. + assert not auth_tools.bcrypt_check_password( + 'notthepassword', + '$2a$12$ELVlnw3z1FMu6CEGs/L8XO8vl0BuWSlUHgh0rUrry9DUXGMUNWwl6', + '3><7R45417') + + +def test_bcrypt_gen_password_hash(): + pw = 'youwillneverguessthis' + + # Normal password hash generation, and check on that hash + hashed_pw = auth_tools.bcrypt_gen_password_hash(pw) + assert auth_tools.bcrypt_check_password( + pw, hashed_pw) + assert not auth_tools.bcrypt_check_password( + 'notthepassword', hashed_pw) + + # Same thing, extra salt. + hashed_pw = auth_tools.bcrypt_gen_password_hash(pw, '3><7R45417') + assert auth_tools.bcrypt_check_password( + pw, hashed_pw, '3><7R45417') + assert not auth_tools.bcrypt_check_password( + 'notthepassword', hashed_pw, '3><7R45417') + + +def test_change_password(test_app): + """Test changing password correctly and incorrectly""" + test_user = fixture_add_user( + password=u'toast', + privileges=[u'active']) + + test_app.post( + '/auth/login/', { + 'username': u'chris', + 'password': u'toast'}) + + # test that the password can be changed + res = test_app.post( + '/edit/password/', { + 'old_password': 'toast', + 'new_password': '123456', + }) + res.follow() + + # Did we redirect to the correct page? + assert urlparse.urlsplit(res.location)[2] == '/edit/account/' + + # test_user has to be fetched again in order to have the current values + test_user = User.query.filter_by(username=u'chris').first() + assert auth_tools.bcrypt_check_password('123456', test_user.pw_hash) + + # test that the password cannot be changed if the given + # old_password is wrong + template.clear_test_template_context() + test_app.post( + '/edit/password/', { + 'old_password': 'toast', + 'new_password': '098765', + }) + + test_user = User.query.filter_by(username=u'chris').first() + assert not auth_tools.bcrypt_check_password('098765', test_user.pw_hash) diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py index 5530c6f2..d60293f9 100644 --- a/mediagoblin/tests/test_celery_setup.py +++ b/mediagoblin/tests/test_celery_setup.py @@ -48,13 +48,13 @@ def test_setup_celery_from_config(): assert isinstance(fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION, float) assert fake_celery_module.CELERY_RESULT_PERSISTENT is True assert fake_celery_module.CELERY_IMPORTS == [ - 'foo.bar.baz', 'this.is.an.import', 'mediagoblin.processing.task'] + 'foo.bar.baz', 'this.is.an.import', 'mediagoblin.processing.task', 'mediagoblin.notifications.task'] assert fake_celery_module.CELERY_RESULT_BACKEND == 'database' assert fake_celery_module.CELERY_RESULT_DBURI == ( 'sqlite:///' + pkg_resources.resource_filename('mediagoblin.tests', 'celery.db')) assert fake_celery_module.BROKER_TRANSPORT == 'sqlalchemy' - assert fake_celery_module.BROKER_HOST == ( + assert fake_celery_module.BROKER_URL == ( 'sqlite:///' + pkg_resources.resource_filename('mediagoblin.tests', 'kombu.db')) diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py index cda2607f..4f44e0b9 100644 --- a/mediagoblin/tests/test_edit.py +++ b/mediagoblin/tests/test_edit.py @@ -14,19 +14,21 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import pytest +import urlparse from mediagoblin import mg_globals from mediagoblin.db.models import User from mediagoblin.tests.tools import fixture_add_user -from mediagoblin.tools import template -from mediagoblin.auth.lib import bcrypt_check_password +from mediagoblin import auth +from mediagoblin.tools import template, mail + class TestUserEdit(object): def setup(self): # set up new user self.user_password = u'toast' - self.user = fixture_add_user(password = self.user_password) + self.user = fixture_add_user(password = self.user_password, + privileges=[u'active']) def login(self, test_app): test_app.post( @@ -51,42 +53,10 @@ class TestUserEdit(object): # deleted too. Perhaps in submission test? #Restore user at end of test - self.user = fixture_add_user(password = self.user_password) - self.login(test_app) - - - def test_change_password(self, test_app): - """Test changing password correctly and incorrectly""" + self.user = fixture_add_user(password = self.user_password, + privileges=[u'active']) self.login(test_app) - # test that the password can be changed - # template.clear_test_template_context() - res = test_app.post( - '/edit/account/', { - 'old_password': 'toast', - 'new_password': '123456', - 'wants_comment_notification': 'y' - }) - - # Check for redirect on success - assert res.status_int == 302 - # test_user has to be fetched again in order to have the current values - test_user = User.query.filter_by(username=u'chris').first() - assert bcrypt_check_password('123456', test_user.pw_hash) - # Update current user passwd - self.user_password = '123456' - - # test that the password cannot be changed if the given - # old_password is wrong template.clear_test_template_context() - test_app.post( - '/edit/account/', { - 'old_password': 'toast', - 'new_password': '098765', - }) - - test_user = User.query.filter_by(username=u'chris').first() - assert not bcrypt_check_password('098765', test_user.pw_hash) - def test_change_bio_url(self, test_app): """Test changing bio and URL""" @@ -112,7 +82,8 @@ class TestUserEdit(object): assert test_user.url == u'http://dustycloud.org/' # change a different user than the logged in (should fail with 403) - fixture_add_user(username=u"foo") + fixture_add_user(username=u"foo", + privileges=[u'active']) res = test_app.post( '/u/foo/edit/', { 'bio': u'I love toast!', @@ -138,4 +109,68 @@ class TestUserEdit(object): assert form.url.errors == [ u'This address contains errors'] + def test_email_change(self, test_app): + self.login(test_app) + + # Test email already in db + template.clear_test_template_context() + test_app.post( + '/edit/email/', { + 'new_email': 'chris@example.com', + 'password': 'toast'}) + + # Check form errors + context = template.TEMPLATE_TEST_CONTEXT[ + 'mediagoblin/edit/change_email.html'] + assert context['form'].new_email.errors == [ + u'Sorry, a user with that email address already exists.'] + + # Test successful email change + template.clear_test_template_context() + res = test_app.post( + '/edit/email/', { + 'new_email': 'new@example.com', + 'password': 'toast'}) + res.follow() + + # Correct redirect? + assert urlparse.urlsplit(res.location)[2] == '/edit/account/' + + # Make sure we get email verification and try verifying + assert len(mail.EMAIL_TEST_INBOX) == 1 + message = mail.EMAIL_TEST_INBOX.pop() + assert message['To'] == 'new@example.com' + email_context = template.TEMPLATE_TEST_CONTEXT[ + 'mediagoblin/edit/verification.txt'] + assert email_context['verification_url'] in \ + message.get_payload(decode=True) + + path = urlparse.urlsplit(email_context['verification_url'])[2] + assert path == u'/edit/verify_email/' + + ## Try verifying with bs verification key, shouldn't work + template.clear_test_template_context() + res = test_app.get( + "/edit/verify_email/?token=total_bs") + res.follow() + + # Correct redirect? + assert urlparse.urlsplit(res.location)[2] == '/' + + # Email shouldn't be saved + email_in_db = mg_globals.database.User.query.filter_by( + email='new@example.com').first() + email = User.query.filter_by(username='chris').first().email + assert email_in_db is None + assert email == 'chris@example.com' + + # Verify email activation works + template.clear_test_template_context() + get_params = urlparse.urlsplit(email_context['verification_url'])[3] + res = test_app.get('%s?%s' % (path, get_params)) + res.follow() + + # New email saved? + email = User.query.filter_by(username='chris').first().email + assert email == 'new@example.com' # test changing the url inproperly diff --git a/mediagoblin/tests/test_exif.py b/mediagoblin/tests/test_exif.py index 824de3c2..c07e24ae 100644 --- a/mediagoblin/tests/test_exif.py +++ b/mediagoblin/tests/test_exif.py @@ -48,63 +48,324 @@ def test_exif_extraction(): assert gps == {} # Do we have the "useful" tags? - assert useful == { - 'EXIF Flash': { - 'field_type': 3, - 'printable': u'Flash did not fire', - 'field_offset': 380, - 'tag': 37385, - 'values': [0], - 'field_length': 2}, - 'EXIF ExposureTime': { - 'field_type': 5, - 'printable': '1/125', - 'field_offset': 700, - 'tag': 33434, - 'values': [[1, 125]], - 'field_length': 8}, - 'EXIF FocalLength': { - 'field_type': 5, - 'printable': '18', - 'field_offset': 780, - 'tag': 37386, - 'values': [[18, 1]], - 'field_length': 8}, - 'Image Model': { - 'field_type': 2, - 'printable': 'NIKON D80', - 'field_offset': 152, - 'tag': 272, - 'values': 'NIKON D80', - 'field_length': 10}, - 'Image Make': { - 'field_type': 2, - 'printable': 'NIKON CORPORATION', - 'field_offset': 134, - 'tag': 271, - 'values': 'NIKON CORPORATION', - 'field_length': 18}, - 'EXIF ExposureMode': { - 'field_type': 3, - 'printable': 'Manual Exposure', - 'field_offset': 584, - 'tag': 41986, - 'values': [1], - 'field_length': 2}, - 'EXIF ISOSpeedRatings': { - 'field_type': 3, - 'printable': '100', - 'field_offset': 260, - 'tag': 34855, - 'values': [100], - 'field_length': 2}, - 'EXIF FNumber': { - 'field_type': 5, - 'printable': '10', - 'field_offset': 708, - 'tag': 33437, - 'values': [[10, 1]], - 'field_length': 8}} + assert useful == {'EXIF CVAPattern': {'field_length': 8, + 'field_offset': 26224, + 'field_type': 7, + 'printable': u'[0, 2, 0, 2, 1, 2, 0, 1]', + 'tag': 41730, + 'values': [0, 2, 0, 2, 1, 2, 0, 1]}, + 'EXIF ColorSpace': {'field_length': 2, + 'field_offset': 476, + 'field_type': 3, + 'printable': u'sRGB', + 'tag': 40961, + 'values': [1]}, + 'EXIF ComponentsConfiguration': {'field_length': 4, + 'field_offset': 308, + 'field_type': 7, + 'printable': u'YCbCr', + 'tag': 37121, + 'values': [1, 2, 3, 0]}, + 'EXIF CompressedBitsPerPixel': {'field_length': 8, + 'field_offset': 756, + 'field_type': 5, + 'printable': u'4', + 'tag': 37122, + 'values': [[4, 1]]}, + 'EXIF Contrast': {'field_length': 2, + 'field_offset': 656, + 'field_type': 3, + 'printable': u'Soft', + 'tag': 41992, + 'values': [1]}, + 'EXIF CustomRendered': {'field_length': 2, + 'field_offset': 572, + 'field_type': 3, + 'printable': u'Normal', + 'tag': 41985, + 'values': [0]}, + 'EXIF DateTimeDigitized': {'field_length': 20, + 'field_offset': 736, + 'field_type': 2, + 'printable': u'2011:06:22 12:20:33', + 'tag': 36868, + 'values': u'2011:06:22 12:20:33'}, + 'EXIF DateTimeOriginal': {'field_length': 20, + 'field_offset': 716, + 'field_type': 2, + 'printable': u'2011:06:22 12:20:33', + 'tag': 36867, + 'values': u'2011:06:22 12:20:33'}, + 'EXIF DigitalZoomRatio': {'field_length': 8, + 'field_offset': 26232, + 'field_type': 5, + 'printable': u'1', + 'tag': 41988, + 'values': [[1, 1]]}, + 'EXIF ExifImageLength': {'field_length': 2, + 'field_offset': 500, + 'field_type': 3, + 'printable': u'2592', + 'tag': 40963, + 'values': [2592]}, + 'EXIF ExifImageWidth': {'field_length': 2, + 'field_offset': 488, + 'field_type': 3, + 'printable': u'3872', + 'tag': 40962, + 'values': [3872]}, + 'EXIF ExifVersion': {'field_length': 4, + 'field_offset': 272, + 'field_type': 7, + 'printable': u'0221', + 'tag': 36864, + 'values': [48, 50, 50, 49]}, + 'EXIF ExposureBiasValue': {'field_length': 8, + 'field_offset': 764, + 'field_type': 10, + 'printable': u'0', + 'tag': 37380, + 'values': [[0, 1]]}, + 'EXIF ExposureMode': {'field_length': 2, + 'field_offset': 584, + 'field_type': 3, + 'printable': u'Manual Exposure', + 'tag': 41986, + 'values': [1]}, + 'EXIF ExposureProgram': {'field_length': 2, + 'field_offset': 248, + 'field_type': 3, + 'printable': u'Manual', + 'tag': 34850, + 'values': [1]}, + 'EXIF ExposureTime': {'field_length': 8, + 'field_offset': 700, + 'field_type': 5, + 'printable': u'1/125', + 'tag': 33434, + 'values': [[1, 125]]}, + 'EXIF FNumber': {'field_length': 8, + 'field_offset': 708, + 'field_type': 5, + 'printable': u'10', + 'tag': 33437, + 'values': [[10, 1]]}, + 'EXIF FileSource': {'field_length': 1, + 'field_offset': 536, + 'field_type': 7, + 'printable': u'Digital Camera', + 'tag': 41728, + 'values': [3]}, + 'EXIF Flash': {'field_length': 2, + 'field_offset': 380, + 'field_type': 3, + 'printable': u'Flash did not fire', + 'tag': 37385, + 'values': [0]}, + 'EXIF FlashPixVersion': {'field_length': 4, + 'field_offset': 464, + 'field_type': 7, + 'printable': u'0100', + 'tag': 40960, + 'values': [48, 49, 48, 48]}, + 'EXIF FocalLength': {'field_length': 8, + 'field_offset': 780, + 'field_type': 5, + 'printable': u'18', + 'tag': 37386, + 'values': [[18, 1]]}, + 'EXIF FocalLengthIn35mmFilm': {'field_length': 2, + 'field_offset': 620, + 'field_type': 3, + 'printable': u'27', + 'tag': 41989, + 'values': [27]}, + 'EXIF GainControl': {'field_length': 2, + 'field_offset': 644, + 'field_type': 3, + 'printable': u'None', + 'tag': 41991, + 'values': [0]}, + 'EXIF ISOSpeedRatings': {'field_length': 2, + 'field_offset': 260, + 'field_type': 3, + 'printable': u'100', + 'tag': 34855, + 'values': [100]}, + 'EXIF InteroperabilityOffset': {'field_length': 4, + 'field_offset': 512, + 'field_type': 4, + 'printable': u'26240', + 'tag': 40965, + 'values': [26240]}, + 'EXIF LightSource': {'field_length': 2, + 'field_offset': 368, + 'field_type': 3, + 'printable': u'Unknown', + 'tag': 37384, + 'values': [0]}, + 'EXIF MaxApertureValue': {'field_length': 8, + 'field_offset': 772, + 'field_type': 5, + 'printable': u'18/5', + 'tag': 37381, + 'values': [[18, 5]]}, + 'EXIF MeteringMode': {'field_length': 2, + 'field_offset': 356, + 'field_type': 3, + 'printable': u'Pattern', + 'tag': 37383, + 'values': [5]}, + 'EXIF Saturation': {'field_length': 2, + 'field_offset': 668, + 'field_type': 3, + 'printable': u'Normal', + 'tag': 41993, + 'values': [0]}, + 'EXIF SceneCaptureType': {'field_length': 2, + 'field_offset': 632, + 'field_type': 3, + 'printable': u'Standard', + 'tag': 41990, + 'values': [0]}, + 'EXIF SceneType': {'field_length': 1, + 'field_offset': 548, + 'field_type': 7, + 'printable': u'Directly Photographed', + 'tag': 41729, + 'values': [1]}, + 'EXIF SensingMethod': {'field_length': 2, + 'field_offset': 524, + 'field_type': 3, + 'printable': u'One-chip color area', + 'tag': 41495, + 'values': [2]}, + 'EXIF Sharpness': {'field_length': 2, + 'field_offset': 680, + 'field_type': 3, + 'printable': u'Normal', + 'tag': 41994, + 'values': [0]}, + 'EXIF SubSecTime': {'field_length': 3, + 'field_offset': 428, + 'field_type': 2, + 'printable': u'10', + 'tag': 37520, + 'values': u'10'}, + 'EXIF SubSecTimeDigitized': {'field_length': 3, + 'field_offset': 452, + 'field_type': 2, + 'printable': u'10', + 'tag': 37522, + 'values': u'10'}, + 'EXIF SubSecTimeOriginal': {'field_length': 3, + 'field_offset': 440, + 'field_type': 2, + 'printable': u'10', + 'tag': 37521, + 'values': u'10'}, + 'EXIF SubjectDistanceRange': {'field_length': 2, + 'field_offset': 692, + 'field_type': 3, + 'printable': u'0', + 'tag': 41996, + 'values': [0]}, + 'EXIF WhiteBalance': {'field_length': 2, + 'field_offset': 596, + 'field_type': 3, + 'printable': u'Auto', + 'tag': 41987, + 'values': [0]}, + 'Image DateTime': {'field_length': 20, + 'field_offset': 194, + 'field_type': 2, + 'printable': u'2011:06:22 12:20:33', + 'tag': 306, + 'values': u'2011:06:22 12:20:33'}, + 'Image ExifOffset': {'field_length': 4, + 'field_offset': 126, + 'field_type': 4, + 'printable': u'214', + 'tag': 34665, + 'values': [214]}, + 'Image Make': {'field_length': 18, + 'field_offset': 134, + 'field_type': 2, + 'printable': u'NIKON CORPORATION', + 'tag': 271, + 'values': u'NIKON CORPORATION'}, + 'Image Model': {'field_length': 10, + 'field_offset': 152, + 'field_type': 2, + 'printable': u'NIKON D80', + 'tag': 272, + 'values': u'NIKON D80'}, + 'Image Orientation': {'field_length': 2, + 'field_offset': 42, + 'field_type': 3, + 'printable': u'Rotated 90 CCW', + 'tag': 274, + 'values': [6]}, + 'Image ResolutionUnit': {'field_length': 2, + 'field_offset': 78, + 'field_type': 3, + 'printable': u'Pixels/Inch', + 'tag': 296, + 'values': [2]}, + 'Image Software': {'field_length': 15, + 'field_offset': 178, + 'field_type': 2, + 'printable': u'Shotwell 0.9.3', + 'tag': 305, + 'values': u'Shotwell 0.9.3'}, + 'Image XResolution': {'field_length': 8, + 'field_offset': 162, + 'field_type': 5, + 'printable': u'300', + 'tag': 282, + 'values': [[300, 1]]}, + 'Image YCbCrPositioning': {'field_length': 2, + 'field_offset': 114, + 'field_type': 3, + 'printable': u'Co-sited', + 'tag': 531, + 'values': [2]}, + 'Image YResolution': {'field_length': 8, + 'field_offset': 170, + 'field_type': 5, + 'printable': u'300', + 'tag': 283, + 'values': [[300, 1]]}, + 'Thumbnail Compression': {'field_length': 2, + 'field_offset': 26280, + 'field_type': 3, + 'printable': u'JPEG (old-style)', + 'tag': 259, + 'values': [6]}, + 'Thumbnail ResolutionUnit': {'field_length': 2, + 'field_offset': 26316, + 'field_type': 3, + 'printable': u'Pixels/Inch', + 'tag': 296, + 'values': [2]}, + 'Thumbnail XResolution': {'field_length': 8, + 'field_offset': 26360, + 'field_type': 5, + 'printable': u'300', + 'tag': 282, + 'values': [[300, 1]]}, + 'Thumbnail YCbCrPositioning': {'field_length': 2, + 'field_offset': 26352, + 'field_type': 3, + 'printable': u'Co-sited', + 'tag': 531, + 'values': [2]}, + 'Thumbnail YResolution': {'field_length': 8, + 'field_offset': 26368, + 'field_type': 5, + 'printable': u'300', + 'tag': 283, + 'values': [[300, 1]]}} def test_exif_image_orientation(): diff --git a/mediagoblin/tests/test_http_callback.py b/mediagoblin/tests/test_http_callback.py index a0511af7..64b7ee8f 100644 --- a/mediagoblin/tests/test_http_callback.py +++ b/mediagoblin/tests/test_http_callback.py @@ -23,7 +23,7 @@ from mediagoblin import mg_globals from mediagoblin.tools import processing from mediagoblin.tests.tools import fixture_add_user from mediagoblin.tests.test_submission import GOOD_PNG -from mediagoblin.tests import test_oauth as oauth +from mediagoblin.tests import test_oauth2 as oauth class TestHTTPCallback(object): @@ -44,7 +44,7 @@ class TestHTTPCallback(object): 'password': self.user_password}) def get_access_token(self, client_id, client_secret, code): - response = self.test_app.get('/oauth/access_token', { + response = self.test_app.get('/oauth-2/access_token', { 'code': code, 'client_id': client_id, 'client_secret': client_secret}) diff --git a/mediagoblin/tests/test_ldap.py b/mediagoblin/tests/test_ldap.py new file mode 100644 index 00000000..48efb4b6 --- /dev/null +++ b/mediagoblin/tests/test_ldap.py @@ -0,0 +1,125 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import urlparse +import pkg_resources +import pytest +import mock + +from mediagoblin import mg_globals +from mediagoblin.db.base import Session +from mediagoblin.tests.tools import get_app +from mediagoblin.tools import template + +pytest.importorskip("ldap") + + +@pytest.fixture() +def ldap_plugin_app(request): + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'mediagoblin.tests.auth_configs', + 'ldap_appconfig.ini')) + + +def return_value(): + return u'chris', u'chris@example.com' + + +def test_ldap_plugin(ldap_plugin_app): + res = ldap_plugin_app.get('/auth/login/') + + assert urlparse.urlsplit(res.location)[2] == '/auth/ldap/login/' + + res = ldap_plugin_app.get('/auth/register/') + + assert urlparse.urlsplit(res.location)[2] == '/auth/ldap/register/' + + res = ldap_plugin_app.get('/auth/ldap/register/') + + assert urlparse.urlsplit(res.location)[2] == '/auth/ldap/login/' + + template.clear_test_template_context() + res = ldap_plugin_app.post( + '/auth/ldap/login/', {}) + + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] + form = context['login_form'] + assert form.username.errors == [u'This field is required.'] + assert form.password.errors == [u'This field is required.'] + + @mock.patch('mediagoblin.plugins.ldap.tools.LDAP.login', mock.Mock(return_value=return_value())) + def _test_authentication(): + template.clear_test_template_context() + res = ldap_plugin_app.post( + '/auth/ldap/login/', + {'username': u'chris', + 'password': u'toast'}) + + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] + register_form = context['register_form'] + + assert register_form.username.data == u'chris' + assert register_form.email.data == u'chris@example.com' + + template.clear_test_template_context() + res = ldap_plugin_app.post( + '/auth/ldap/register/', + {'username': u'chris', + 'email': u'chris@example.com'}) + res.follow() + + assert urlparse.urlsplit(res.location)[2] == '/u/chris/' + assert 'mediagoblin/user_pages/user_nonactive.html' in template.TEMPLATE_TEST_CONTEXT + + # Try to register with same email and username + template.clear_test_template_context() + res = ldap_plugin_app.post( + '/auth/ldap/register/', + {'username': u'chris', + 'email': u'chris@example.com'}) + + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] + register_form = context['register_form'] + + assert register_form.email.errors == [u'Sorry, a user with that email address already exists.'] + assert register_form.username.errors == [u'Sorry, a user with that name already exists.'] + + # Log out + ldap_plugin_app.get('/auth/logout/') + + # Get user and detach from session + test_user = mg_globals.database.User.query.filter_by( + username=u'chris').first() + Session.expunge(test_user) + + # Log back in + template.clear_test_template_context() + res = ldap_plugin_app.post( + '/auth/ldap/login/', + {'username': u'chris', + 'password': u'toast'}) + res.follow() + + assert urlparse.urlsplit(res.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT + + # Make sure user is in the session + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] + session = context['request'].session + assert session['user_id'] == unicode(test_user.id) + + _test_authentication() diff --git a/mediagoblin/tests/test_messages.py b/mediagoblin/tests/test_messages.py index 3ac917b0..22f9e800 100644 --- a/mediagoblin/tests/test_messages.py +++ b/mediagoblin/tests/test_messages.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from mediagoblin.messages import fetch_messages, add_message +from mediagoblin import messages from mediagoblin.tools import template @@ -32,11 +32,19 @@ def test_messages(test_app): # The message queue should be empty assert request.session.get('messages', []) == [] + # First of all, we should clear the messages queue + messages.clear_add_message() # Adding a message should modify the session accordingly - add_message(request, 'herp_derp', 'First!') + messages.add_message(request, 'herp_derp', 'First!') test_msg_queue = [{'text': 'First!', 'level': 'herp_derp'}] - assert request.session['messages'] == test_msg_queue + + # Alternative tests to the following, test divided in two steps: + # assert request.session['messages'] == test_msg_queue + # 1. Tests if add_message worked + assert messages.ADD_MESSAGE_TEST[-1] == test_msg_queue + # 2. Tests if add_message updated session information + assert messages.ADD_MESSAGE_TEST[-1] == request.session['messages'] # fetch_messages should return and empty the queue - assert fetch_messages(request) == test_msg_queue + assert messages.fetch_messages(request) == test_msg_queue assert request.session.get('messages') == [] diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index 9f95a398..4cd3d9b6 100644 --- a/mediagoblin/tests/test_mgoblin_app.ini +++ b/mediagoblin/tests/test_mgoblin_app.ini @@ -3,8 +3,9 @@ direct_remote_path = /test_static/ email_sender_address = "notice@mediagoblin.example.org" email_debug_mode = true -# TODO: Switch to using an in-memory database -sql_engine = "sqlite:///%(here)s/test_user_dev/mediagoblin.db" +#Runs with an in-memory sqlite db for speed. +sql_engine = "sqlite://" +run_migrations = true # tag parsing tags_max_length = 50 @@ -12,26 +13,28 @@ tags_max_length = 50 # So we can start to test attachments: allow_attachments = True -# Celery shouldn't be set up by the application as it's setup via -# mediagoblin.init.celery.from_celery -celery_setup_elsewhere = true +upload_limit = 500 -media_types = mediagoblin.media_types.image, mediagoblin.media_types.pdf +max_file_size = 2 [storage:publicstore] -base_dir = %(here)s/test_user_dev/media/public +base_dir = %(here)s/user_dev/media/public base_url = /mgoblin_media/ [storage:queuestore] -base_dir = %(here)s/test_user_dev/media/queue +base_dir = %(here)s/user_dev/media/queue [celery] CELERY_ALWAYS_EAGER = true -CELERY_RESULT_DBURI = "sqlite:///%(here)s/test_user_dev/celery.db" -BROKER_HOST = "sqlite:///%(here)s/test_user_dev/kombu.db" +CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db" +BROKER_URL = "sqlite:///%(here)s/test_user_dev/kombu.db" [plugins] [[mediagoblin.plugins.api]] [[mediagoblin.plugins.oauth]] [[mediagoblin.plugins.httpapiauth]] - +[[mediagoblin.plugins.piwigo]] +[[mediagoblin.plugins.basic_auth]] +[[mediagoblin.plugins.openid]] +[[mediagoblin.media_types.image]] +[[mediagoblin.media_types.pdf]] diff --git a/mediagoblin/tests/test_misc.py b/mediagoblin/tests/test_misc.py index 755d863f..43ad0b6d 100644 --- a/mediagoblin/tests/test_misc.py +++ b/mediagoblin/tests/test_misc.py @@ -28,8 +28,10 @@ def test_user_deletes_other_comments(test_app): user_a = fixture_add_user(u"chris_a") user_b = fixture_add_user(u"chris_b") - media_a = fixture_media_entry(uploader=user_a.id, save=False) - media_b = fixture_media_entry(uploader=user_b.id, save=False) + media_a = fixture_media_entry(uploader=user_a.id, save=False, + expunge=False, fake_upload=False) + media_b = fixture_media_entry(uploader=user_b.id, save=False, + expunge=False, fake_upload=False) Session.add(media_a) Session.add(media_b) Session.flush() @@ -79,7 +81,7 @@ def test_user_deletes_other_comments(test_app): def test_media_deletes_broken_attachment(test_app): user_a = fixture_add_user(u"chris_a") - media = fixture_media_entry(uploader=user_a.id, save=False) + media = fixture_media_entry(uploader=user_a.id, save=False, expunge=False) media.attachment_files.append(dict( name=u"some name", filepath=[u"does", u"not", u"exist"], diff --git a/mediagoblin/tests/test_modelmethods.py b/mediagoblin/tests/test_modelmethods.py index 427aa47c..86513c76 100644 --- a/mediagoblin/tests/test_modelmethods.py +++ b/mediagoblin/tests/test_modelmethods.py @@ -18,7 +18,7 @@ # methods, and so it makes sense to test them here. from mediagoblin.db.base import Session -from mediagoblin.db.models import MediaEntry +from mediagoblin.db.models import MediaEntry, User, Privilege from mediagoblin.tests.tools import fixture_add_user @@ -47,7 +47,7 @@ class TestMediaEntrySlugs(object): entry.id = this_id entry.uploader = uploader or self.chris_user.id entry.media_type = u'image' - + if save: entry.save() @@ -99,7 +99,7 @@ class TestMediaEntrySlugs(object): u"Beware, I exist!!", this_id=9000, save=False) entry.generate_slug() assert entry.slug == u"beware-i-exist-test" - + _real_test() def test_existing_slug_cant_use_id_extra_junk(self, test_app): @@ -151,6 +151,44 @@ class TestMediaEntrySlugs(object): qbert_entry.generate_slug() assert qbert_entry.slug is None +class TestUserHasPrivilege: + def _setup(self): + fixture_add_user(u'natalie', + privileges=[u'admin',u'moderator',u'active']) + fixture_add_user(u'aeva', + privileges=[u'moderator',u'active']) + self.natalie_user = User.query.filter( + User.username==u'natalie').first() + self.aeva_user = User.query.filter( + User.username==u'aeva').first() + + def test_privilege_added_correctly(self, test_app): + self._setup() + admin = Privilege.query.filter( + Privilege.privilege_name == u'admin').one() + # first make sure the privileges were added successfully + + assert admin in self.natalie_user.all_privileges + assert admin not in self.aeva_user.all_privileges + + def test_user_has_privilege_one(self, test_app): + self._setup() + + # then test out the user.has_privilege method for one privilege + assert not self.natalie_user.has_privilege(u'commenter') + assert self.aeva_user.has_privilege(u'active') + + + def test_user_has_privileges_multiple(self, test_app): + self._setup() + + # when multiple args are passed to has_privilege, the method returns + # True if the user has ANY of the privileges + assert self.natalie_user.has_privilege(u'admin',u'commenter') + assert self.aeva_user.has_privilege(u'moderator',u'active') + assert not self.natalie_user.has_privilege(u'commenter',u'uploader') + + def test_media_data_init(test_app): Session.rollback() @@ -165,3 +203,4 @@ def test_media_data_init(test_app): obj_in_session += 1 print repr(obj) assert obj_in_session == 0 + diff --git a/mediagoblin/tests/test_moderation.py b/mediagoblin/tests/test_moderation.py new file mode 100644 index 00000000..e7a0ebef --- /dev/null +++ b/mediagoblin/tests/test_moderation.py @@ -0,0 +1,242 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import pytest + +from mediagoblin.tests.tools import (fixture_add_user, + fixture_add_comment_report, fixture_add_comment) +from mediagoblin.db.models import User, CommentReport, MediaComment, UserBan +from mediagoblin.tools import template, mail +from webtest import AppError + +class TestModerationViews: + @pytest.fixture(autouse=True) + def _setup(self, test_app): + self.test_app = test_app + + fixture_add_user(u'admin', + privileges=[u'admin',u'active']) + fixture_add_user(u'moderator', + privileges=[u'moderator',u'active']) + fixture_add_user(u'regular', + privileges=[u'active',u'commenter']) + self.query_for_users() + + def login(self, username): + self.test_app.post( + '/auth/login/', { + 'username': username, + 'password': 'toast'}) + self.query_for_users() + + def logout(self): + self.test_app.get('/auth/logout/') + self.query_for_users() + + def query_for_users(self): + self.admin_user = User.query.filter(User.username==u'admin').first() + self.mod_user = User.query.filter(User.username==u'moderator').first() + self.user = User.query.filter(User.username==u'regular').first() + + def do_post(self, data, *context_keys, **kwargs): + url = kwargs.pop('url', '/submit/') + do_follow = kwargs.pop('do_follow', False) + template.clear_test_template_context() + response = self.test_app.post(url, data, **kwargs) + if do_follow: + response.follow() + context_data = template.TEMPLATE_TEST_CONTEXT + for key in context_keys: + context_data = context_data[key] + return response, context_data + + def testGiveOrTakeAwayPrivileges(self): + self.login(u'admin') + # First, test an admin taking away a privilege from a user + #---------------------------------------------------------------------- + response, context = self.do_post({'privilege_name':u'commenter'}, + url='/mod/users/{0}/privilege/'.format(self.user.username)) + assert response.status == '302 FOUND' + self.query_for_users() + assert not self.user.has_privilege(u'commenter') + + # Then, test an admin giving a privilege to a user + #---------------------------------------------------------------------- + response, context = self.do_post({'privilege_name':u'commenter'}, + url='/mod/users/{0}/privilege/'.format(self.user.username)) + assert response.status == '302 FOUND' + self.query_for_users() + assert self.user.has_privilege(u'commenter') + + # Then, test a mod trying to take away a privilege from a user + # they are not allowed to do this, so this will raise an error + #---------------------------------------------------------------------- + self.logout() + self.login(u'moderator') + + with pytest.raises(AppError) as excinfo: + response, context = self.do_post({'privilege_name':u'commenter'}, + url='/mod/users/{0}/privilege/'.format(self.user.username)) + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + self.query_for_users() + + assert self.user.has_privilege(u'commenter') + + def testReportResolution(self): + self.login(u'moderator') + + # First, test a moderators taking away a user's privilege in response + # to a reported comment + #---------------------------------------------------------------------- + fixture_add_comment_report(reported_user=self.user) + comment_report = CommentReport.query.filter( + CommentReport.reported_user==self.user).first() + + response = self.test_app.get('/mod/reports/{0}/'.format( + comment_report.id)) + assert response.status == '200 OK' + self.query_for_users() + comment_report = CommentReport.query.filter( + CommentReport.reported_user==self.user).first() + + response, context = self.do_post({'action_to_resolve':[u'takeaway'], + 'take_away_privileges':[u'commenter'], + 'targeted_user':self.user.id}, + url='/mod/reports/{0}/'.format(comment_report.id)) + + self.query_for_users() + comment_report = CommentReport.query.filter( + CommentReport.reported_user==self.user).first() + assert response.status == '302 FOUND' + assert not self.user.has_privilege(u'commenter') + assert comment_report.is_archived_report() is True + + fixture_add_comment_report(reported_user=self.user) + comment_report = CommentReport.query.filter( + CommentReport.reported_user==self.user).first() + + # Then, test a moderator sending an email to a user in response to a + # reported comment + #---------------------------------------------------------------------- + self.query_for_users() + + response, context = self.do_post({'action_to_resolve':[u'sendmessage'], + 'message_to_user':'This is your last warning, regular....', + 'targeted_user':self.user.id}, + url='/mod/reports/{0}/'.format(comment_report.id)) + + self.query_for_users() + comment_report = CommentReport.query.filter( + CommentReport.reported_user==self.user).first() + assert response.status == '302 FOUND' + assert mail.EMAIL_TEST_MBOX_INBOX == [{'to': [u'regular@example.com'], + 'message': 'Content-Type: text/plain; charset="utf-8"\n\ +MIME-Version: 1.0\nContent-Transfer-Encoding: base64\nSubject: Warning from- \ +moderator \nFrom: notice@mediagoblin.example.org\nTo: regular@example.com\n\n\ +VGhpcyBpcyB5b3VyIGxhc3Qgd2FybmluZywgcmVndWxhci4uLi4=\n', + 'from': 'notice@mediagoblin.example.org'}] + assert comment_report.is_archived_report() is True + + # Then test a moderator banning a user AND a moderator deleting the + # offending comment. This also serves as a test for taking multiple + # actions to resolve a report + #---------------------------------------------------------------------- + self.query_for_users() + fixture_add_comment(author=self.user.id, + comment=u'Comment will be removed') + test_comment = MediaComment.query.filter( + MediaComment.author==self.user.id).first() + fixture_add_comment_report(comment=test_comment, + reported_user=self.user) + comment_report = CommentReport.query.filter( + CommentReport.comment==test_comment).filter( + CommentReport.resolved==None).first() + + response, context = self.do_post( + {'action_to_resolve':[u'userban', u'delete'], + 'targeted_user':self.user.id, + 'why_user_was_banned':u'', + 'user_banned_until':u''}, + url='/mod/reports/{0}/'.format(comment_report.id)) + assert response.status == '302 FOUND' + self.query_for_users() + test_user_ban = UserBan.query.filter( + UserBan.user_id == self.user.id).first() + assert test_user_ban is not None + test_comment = MediaComment.query.filter( + MediaComment.author==self.user.id).first() + assert test_comment is None + + # Then, test what happens when a moderator attempts to punish an admin + # from a reported comment on an admin. + #---------------------------------------------------------------------- + fixture_add_comment_report(reported_user=self.admin_user) + comment_report = CommentReport.query.filter( + CommentReport.reported_user==self.admin_user).filter( + CommentReport.resolved==None).first() + + response, context = self.do_post({'action_to_resolve':[u'takeaway'], + 'take_away_privileges':[u'active'], + 'targeted_user':self.admin_user.id}, + url='/mod/reports/{0}/'.format(comment_report.id)) + self.query_for_users() + + assert response.status == '200 OK' + assert self.admin_user.has_privilege(u'active') + + def testAllModerationViews(self): + self.login(u'moderator') + username = self.user.username + self.query_for_users() + fixture_add_comment_report(reported_user=self.admin_user) + response = self.test_app.get('/mod/reports/') + assert response.status == "200 OK" + + response = self.test_app.get('/mod/reports/1/') + assert response.status == "200 OK" + + response = self.test_app.get('/mod/users/') + assert response.status == "200 OK" + + user_page_url = '/mod/users/{0}/'.format(username) + response = self.test_app.get(user_page_url) + assert response.status == "200 OK" + + self.test_app.get('/mod/media/') + assert response.status == "200 OK" + + def testBanUnBanUser(self): + self.login(u'admin') + username = self.user.username + user_id = self.user.id + ban_url = '/mod/users/{0}/ban/'.format(username) + response, context = self.do_post({ + 'user_banned_until':u'', + 'why_user_was_banned':u'Because I said so'}, + url=ban_url) + + assert response.status == "302 FOUND" + user_banned = UserBan.query.filter(UserBan.user_id==user_id).first() + assert user_banned is not None + assert user_banned.expiration_date is None + assert user_banned.reason == u'Because I said so' + + response, context = self.do_post({}, + url=ban_url) + + assert response.status == "302 FOUND" + user_banned = UserBan.query.filter(UserBan.user_id==user_id).first() + assert user_banned is None diff --git a/mediagoblin/tests/test_notifications.py b/mediagoblin/tests/test_notifications.py new file mode 100644 index 00000000..3bf36f5f --- /dev/null +++ b/mediagoblin/tests/test_notifications.py @@ -0,0 +1,209 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import pytest + +import urlparse + +from mediagoblin.tools import template, mail + +from mediagoblin.db.models import Notification, CommentNotification, \ + CommentSubscription +from mediagoblin.db.base import Session + +from mediagoblin.notifications import mark_comment_notification_seen + +from mediagoblin.tests.tools import fixture_add_comment, \ + fixture_media_entry, fixture_add_user, \ + fixture_comment_subscription + + +class TestNotifications: + @pytest.fixture(autouse=True) + def setup(self, test_app): + self.test_app = test_app + + # TODO: Possibly abstract into a decorator like: + # @as_authenticated_user('chris') + self.test_user = fixture_add_user(privileges=[u'active',u'commenter']) + + self.current_user = None + + self.login() + + def login(self, username=u'chris', password=u'toast'): + response = self.test_app.post( + '/auth/login/', { + 'username': username, + 'password': password}) + + response.follow() + + assert urlparse.urlsplit(response.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT + + ctx = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] + + assert Session.merge(ctx['request'].user).username == username + + self.current_user = ctx['request'].user + + def logout(self): + self.test_app.get('/auth/logout/') + self.current_user = None + + @pytest.mark.parametrize('wants_email', [True, False]) + def test_comment_notification(self, wants_email): + ''' + Test + - if a notification is created when posting a comment on + another users media entry. + - that the comment data is consistent and exists. + + ''' + user = fixture_add_user('otherperson', password='nosreprehto', + wants_comment_notification=wants_email, + privileges=[u'active',u'commenter']) + + assert user.wants_comment_notification == wants_email + + user_id = user.id + + media_entry = fixture_media_entry(uploader=user.id, state=u'processed') + + media_entry_id = media_entry.id + + subscription = fixture_comment_subscription(media_entry) + + subscription_id = subscription.id + + media_uri_id = '/u/{0}/m/{1}/'.format(user.username, + media_entry.id) + media_uri_slug = '/u/{0}/m/{1}/'.format(user.username, + media_entry.slug) + + self.test_app.post( + media_uri_id + 'comment/add/', + { + 'comment_content': u'Test comment #42' + } + ) + + notifications = Notification.query.filter_by( + user_id=user.id).all() + + assert len(notifications) == 1 + + notification = notifications[0] + + assert type(notification) == CommentNotification + assert notification.seen == False + assert notification.user_id == user.id + assert notification.subject.get_author.id == self.test_user.id + assert notification.subject.content == u'Test comment #42' + + if wants_email == True: + assert mail.EMAIL_TEST_MBOX_INBOX == [ + {'from': 'notice@mediagoblin.example.org', + 'message': 'Content-Type: text/plain; \ +charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: \ +base64\nSubject: GNU MediaGoblin - chris commented on your \ +post\nFrom: notice@mediagoblin.example.org\nTo: \ +otherperson@example.com\n\nSGkgb3RoZXJwZXJzb24sCmNocmlzIGNvbW1lbnRlZCBvbiB5b3VyIHBvc3QgKGh0dHA6Ly9sb2Nh\nbGhvc3Q6ODAvdS9vdGhlcnBlcnNvbi9tL3NvbWUtdGl0bGUvYy8xLyNjb21tZW50KSBhdCBHTlUg\nTWVkaWFHb2JsaW4KClRlc3QgY29tbWVudCAjNDIKCkdOVSBNZWRpYUdvYmxpbg==\n', + 'to': [u'otherperson@example.com']}] + else: + assert mail.EMAIL_TEST_MBOX_INBOX == [] + + + # Save the ids temporarily because of DetachedInstanceError + notification_id = notification.id + comment_id = notification.subject.id + + self.logout() + self.login('otherperson', 'nosreprehto') + + self.test_app.get(media_uri_slug + '/c/{0}/'.format(comment_id)) + + notification = Notification.query.filter_by(id=notification_id).first() + + assert notification.seen == True + + self.test_app.get(media_uri_slug + '/notifications/silence/') + + subscription = CommentSubscription.query.filter_by(id=subscription_id)\ + .first() + + assert subscription.notify == False + + notifications = Notification.query.filter_by( + user_id=user_id).all() + + # User should not have been notified + assert len(notifications) == 1 + + def test_mark_all_comment_notifications_seen(self): + """ Test that mark_all_comments_seen works""" + + user = fixture_add_user('otherperson', password='nosreprehto', + privileges=[u'active']) + + media_entry = fixture_media_entry(uploader=user.id, state=u'processed') + + fixture_comment_subscription(media_entry) + + media_uri_id = '/u/{0}/m/{1}/'.format(user.username, + media_entry.id) + + # add 2 comments + self.test_app.post( + media_uri_id + 'comment/add/', + { + 'comment_content': u'Test comment #43' + } + ) + + self.test_app.post( + media_uri_id + 'comment/add/', + { + 'comment_content': u'Test comment #44' + } + ) + + notifications = Notification.query.filter_by( + user_id=user.id).all() + + assert len(notifications) == 2 + + # both comments should not be marked seen + assert notifications[0].seen == False + assert notifications[1].seen == False + + # login with other user to mark notifications seen + self.logout() + self.login('otherperson', 'nosreprehto') + + # mark all comment notifications seen + res = self.test_app.get('/notifications/comments/mark_all_seen/') + res.follow() + + assert urlparse.urlsplit(res.location)[2] == '/' + + notifications = Notification.query.filter_by( + user_id=user.id).all() + + # both notifications should be marked seen + assert notifications[0].seen == True + assert notifications[1].seen == True diff --git a/mediagoblin/tests/test_oauth1.py b/mediagoblin/tests/test_oauth1.py new file mode 100644 index 00000000..073c2884 --- /dev/null +++ b/mediagoblin/tests/test_oauth1.py @@ -0,0 +1,166 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import cgi + +import pytest +from urlparse import parse_qs, urlparse + +from oauthlib.oauth1 import Client + +from mediagoblin import mg_globals +from mediagoblin.tools import template, pluginapi +from mediagoblin.tests.tools import fixture_add_user + + +class TestOAuth(object): + + MIME_FORM = "application/x-www-form-urlencoded" + MIME_JSON = "application/json" + + @pytest.fixture(autouse=True) + def setup(self, test_app): + self.test_app = test_app + + self.db = mg_globals.database + + self.pman = pluginapi.PluginManager() + + self.user_password = "AUserPassword123" + self.user = fixture_add_user("OAuthy", self.user_password) + + self.login() + + def login(self): + self.test_app.post( + "/auth/login/", { + "username": self.user.username, + "password": self.user_password}) + + def register_client(self, **kwargs): + """ Regiters a client with the API """ + + kwargs["type"] = "client_associate" + kwargs["application_type"] = kwargs.get("application_type", "native") + return self.test_app.post("/api/client/register", kwargs) + + def test_client_client_register_limited_info(self): + """ Tests that a client can be registered with limited information """ + response = self.register_client() + client_info = response.json + + client = self.db.Client.query.filter_by(id=client_info["client_id"]).first() + + assert response.status_int == 200 + assert client is not None + + def test_client_register_full_info(self): + """ Provides every piece of information possible to register client """ + query = { + "application_name": "Testificate MD", + "application_type": "web", + "contacts": "someone@someplace.com tuteo@tsengeo.lu", + "logo_url": "http://ayrel.com/utral.png", + "redirect_uris": "http://navi-kosman.lu http://gmg-yawne-oeru.lu", + } + + response = self.register_client(**query) + client_info = response.json + + client = self.db.Client.query.filter_by(id=client_info["client_id"]).first() + + assert client is not None + assert client.secret == client_info["client_secret"] + assert client.application_type == query["application_type"] + assert client.redirect_uri == query["redirect_uris"].split() + assert client.logo_url == query["logo_url"] + assert client.contacts == query["contacts"].split() + + + def test_client_update(self): + """ Tests that you can update a client """ + # first we need to register a client + response = self.register_client() + + client_info = response.json + client = self.db.Client.query.filter_by(id=client_info["client_id"]).first() + + # Now update + update_query = { + "type": "client_update", + "application_name": "neytiri", + "contacts": "someone@someplace.com abc@cba.com", + "logo_url": "http://place.com/picture.png", + "application_type": "web", + "redirect_uris": "http://blah.gmg/whatever https://inboxen.org/", + } + + update_response = self.register_client(**update_query) + + assert update_response.status_int == 200 + client_info = update_response.json + client = self.db.Client.query.filter_by(id=client_info["client_id"]).first() + + assert client.secret == client_info["client_secret"] + assert client.application_type == update_query["application_type"] + assert client.application_name == update_query["application_name"] + assert client.contacts == update_query["contacts"].split() + assert client.logo_url == update_query["logo_url"] + assert client.redirect_uri == update_query["redirect_uris"].split() + + def to_authorize_headers(self, data): + headers = "" + for key, value in data.items(): + headers += '{0}="{1}",'.format(key, value) + return {"Authorization": "OAuth " + headers[:-1]} + + def test_request_token(self): + """ Test a request for a request token """ + response = self.register_client() + + client_id = response.json["client_id"] + + endpoint = "/oauth/request_token" + request_query = { + "oauth_consumer_key": client_id, + "oauth_nonce": "abcdefghij", + "oauth_timestamp": 123456789.0, + "oauth_callback": "https://some.url/callback", + } + + headers = self.to_authorize_headers(request_query) + + headers["Content-Type"] = self.MIME_FORM + + response = self.test_app.post(endpoint, headers=headers) + response = cgi.parse_qs(response.body) + + # each element is a list, reduce it to a string + for key, value in response.items(): + response[key] = value[0] + + request_token = self.db.RequestToken.query.filter_by( + token=response["oauth_token"] + ).first() + + client = self.db.Client.query.filter_by(id=client_id).first() + + assert request_token is not None + assert request_token.secret == response["oauth_token_secret"] + assert request_token.client == client.id + assert request_token.used == False + assert request_token.callback == request_query["oauth_callback"] + diff --git a/mediagoblin/tests/test_oauth.py b/mediagoblin/tests/test_oauth2.py index ea3bd798..957f4e65 100644 --- a/mediagoblin/tests/test_oauth.py +++ b/mediagoblin/tests/test_oauth2.py @@ -38,7 +38,8 @@ class TestOAuth(object): self.pman = pluginapi.PluginManager() self.user_password = u'4cc355_70k3N' - self.user = fixture_add_user(u'joauth', self.user_password) + self.user = fixture_add_user(u'joauth', self.user_password, + privileges=[u'active']) self.login() @@ -51,7 +52,7 @@ class TestOAuth(object): def register_client(self, name, client_type, description=None, redirect_uri=''): return self.test_app.post( - '/oauth/client/register', { + '/oauth-2/client/register', { 'name': name, 'description': description, 'type': client_type, @@ -115,7 +116,7 @@ class TestOAuth(object): client_identifier = client.identifier redirect_uri = 'https://foo.example' - response = self.test_app.get('/oauth/authorize', { + response = self.test_app.get('/oauth-2/authorize', { 'client_id': client.identifier, 'scope': 'all', 'redirect_uri': redirect_uri}) @@ -129,7 +130,7 @@ class TestOAuth(object): # Short for client authorization post reponse capr = self.test_app.post( - '/oauth/client/authorize', { + '/oauth-2/client/authorize', { 'client_id': form.client_id.data, 'allow': 'Allow', 'next': form.next.data}) @@ -155,7 +156,7 @@ class TestOAuth(object): client = self.db.OAuthClient.query.filter( self.db.OAuthClient.identifier == unicode(client_id)).first() - token_res = self.test_app.get('/oauth/access_token?client_id={0}&\ + token_res = self.test_app.get('/oauth-2/access_token?client_id={0}&\ code={1}&client_secret={2}'.format(client_id, code, client.secret)) assert token_res.status_int == 200 @@ -183,7 +184,7 @@ code={1}&client_secret={2}'.format(client_id, code, client.secret)) client = self.db.OAuthClient.query.filter( self.db.OAuthClient.identifier == unicode(client_id)).first() - token_res = self.test_app.get('/oauth/access_token?\ + token_res = self.test_app.get('/oauth-2/access_token?\ code={0}&client_secret={1}'.format(code, client.secret)) assert token_res.status_int == 200 @@ -204,7 +205,7 @@ code={0}&client_secret={1}'.format(code, client.secret)) client = self.db.OAuthClient.query.filter( self.db.OAuthClient.identifier == client_id).first() - token_res = self.test_app.get('/oauth/access_token', + token_res = self.test_app.get('/oauth-2/access_token', {'refresh_token': token_data['refresh_token'], 'client_id': client_id, 'client_secret': client.secret diff --git a/mediagoblin/tests/test_openid.py b/mediagoblin/tests/test_openid.py new file mode 100644 index 00000000..0424fdda --- /dev/null +++ b/mediagoblin/tests/test_openid.py @@ -0,0 +1,374 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import urlparse +import pkg_resources +import pytest +import mock + +openid_consumer = pytest.importorskip( + "openid.consumer.consumer") + +from mediagoblin import mg_globals +from mediagoblin.db.base import Session +from mediagoblin.db.models import User +from mediagoblin.plugins.openid.models import OpenIDUserURL +from mediagoblin.tests.tools import get_app, fixture_add_user +from mediagoblin.tools import template + + +# App with plugin enabled +@pytest.fixture() +def openid_plugin_app(request): + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'mediagoblin.tests.auth_configs', + 'openid_appconfig.ini')) + + +class TestOpenIDPlugin(object): + def _setup(self, openid_plugin_app, value=True, edit=False, delete=False): + if value: + response = openid_consumer.SuccessResponse(mock.Mock(), mock.Mock()) + if edit or delete: + response.identity_url = u'http://add.myopenid.com' + else: + response.identity_url = u'http://real.myopenid.com' + self._finish_verification = mock.Mock(return_value=response) + else: + self._finish_verification = mock.Mock(return_value=False) + + @mock.patch('mediagoblin.plugins.openid.views._response_email', mock.Mock(return_value=None)) + @mock.patch('mediagoblin.plugins.openid.views._response_nickname', mock.Mock(return_value=None)) + @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) + def _setup_start(self, openid_plugin_app, edit, delete): + if edit: + self._start_verification = mock.Mock(return_value=openid_plugin_app.post( + '/edit/openid/finish/')) + elif delete: + self._start_verification = mock.Mock(return_value=openid_plugin_app.post( + '/edit/openid/delete/finish/')) + else: + self._start_verification = mock.Mock(return_value=openid_plugin_app.post( + '/auth/openid/login/finish/')) + _setup_start(self, openid_plugin_app, edit, delete) + + def test_bad_login(self, openid_plugin_app): + """ Test that attempts to login with invalid paramaters""" + + # Test GET request for auth/register page + res = openid_plugin_app.get('/auth/register/').follow() + + # Make sure it redirected to the correct place + assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' + + # Test GET request for auth/login page + res = openid_plugin_app.get('/auth/login/') + res.follow() + + # Correct redirect? + assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' + + # Test GET request for auth/openid/register page + res = openid_plugin_app.get('/auth/openid/register/') + res.follow() + + # Correct redirect? + assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' + + # Test GET request for auth/openid/login/finish page + res = openid_plugin_app.get('/auth/openid/login/finish/') + res.follow() + + # Correct redirect? + assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' + + # Test GET request for auth/openid/login page + res = openid_plugin_app.get('/auth/openid/login/') + + # Correct place? + assert 'mediagoblin/plugins/openid/login.html' in template.TEMPLATE_TEST_CONTEXT + + # Try to login with an empty form + template.clear_test_template_context() + openid_plugin_app.post( + '/auth/openid/login/', {}) + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/login.html'] + form = context['login_form'] + assert form.openid.errors == [u'This field is required.'] + + # Try to login with wrong form values + template.clear_test_template_context() + openid_plugin_app.post( + '/auth/openid/login/', { + 'openid': 'not_a_url.com'}) + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/login.html'] + form = context['login_form'] + assert form.openid.errors == [u'Please enter a valid url.'] + + # Should be no users in the db + assert User.query.count() == 0 + + # Phony OpenID URl + template.clear_test_template_context() + openid_plugin_app.post( + '/auth/openid/login/', { + 'openid': 'http://phoney.myopenid.com/'}) + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/login.html'] + form = context['login_form'] + assert form.openid.errors == [u'Sorry, the OpenID server could not be found'] + + def test_login(self, openid_plugin_app): + """Tests that test login and registion with openid""" + # Test finish_login redirects correctly when response = False + self._setup(openid_plugin_app, False) + + @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) + @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) + def _test_non_response(): + template.clear_test_template_context() + res = openid_plugin_app.post( + '/auth/openid/login/', { + 'openid': 'http://phoney.myopenid.com/'}) + res.follow() + + # Correct Place? + assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' + assert 'mediagoblin/plugins/openid/login.html' in template.TEMPLATE_TEST_CONTEXT + _test_non_response() + + # Test login with new openid + # Need to clear_test_template_context before calling _setup + template.clear_test_template_context() + self._setup(openid_plugin_app) + + @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) + @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) + def _test_new_user(): + openid_plugin_app.post( + '/auth/openid/login/', { + 'openid': u'http://real.myopenid.com'}) + + # Right place? + assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] + register_form = context['register_form'] + + # Register User + res = openid_plugin_app.post( + '/auth/openid/register/', { + 'openid': register_form.openid.data, + 'username': u'chris', + 'email': u'chris@example.com'}) + res.follow() + + # Correct place? + assert urlparse.urlsplit(res.location)[2] == '/u/chris/' + assert 'mediagoblin/user_pages/user_nonactive.html' in template.TEMPLATE_TEST_CONTEXT + + # No need to test if user is in logged in and verification email + # awaits, since openid uses the register_user function which is + # tested in test_auth + + # Logout User + openid_plugin_app.get('/auth/logout') + + # Get user and detach from session + test_user = mg_globals.database.User.query.filter_by( + username=u'chris').first() + Session.expunge(test_user) + + # Log back in + # Could not get it to work by 'POST'ing to /auth/openid/login/ + template.clear_test_template_context() + res = openid_plugin_app.post( + '/auth/openid/login/finish/', { + 'openid': u'http://real.myopenid.com'}) + res.follow() + + assert urlparse.urlsplit(res.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT + + # Make sure user is in the session + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] + session = context['request'].session + assert session['user_id'] == unicode(test_user.id) + + _test_new_user() + + # Test register with empty form + template.clear_test_template_context() + openid_plugin_app.post( + '/auth/openid/register/', {}) + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] + register_form = context['register_form'] + + assert register_form.openid.errors == [u'This field is required.'] + assert register_form.email.errors == [u'This field is required.'] + assert register_form.username.errors == [u'This field is required.'] + + # Try to register with existing username and email + template.clear_test_template_context() + openid_plugin_app.post( + '/auth/openid/register/', { + 'openid': 'http://real.myopenid.com', + 'email': 'chris@example.com', + 'username': 'chris'}) + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] + register_form = context['register_form'] + + assert register_form.username.errors == [u'Sorry, a user with that name already exists.'] + assert register_form.email.errors == [u'Sorry, a user with that email address already exists.'] + assert register_form.openid.errors == [u'Sorry, an account is already registered to that OpenID.'] + + def test_add_delete(self, openid_plugin_app): + """Test adding and deleting openids""" + # Add user + test_user = fixture_add_user(password='', privileges=[u'active']) + openid = OpenIDUserURL() + openid.openid_url = 'http://real.myopenid.com' + openid.user_id = test_user.id + openid.save() + + # Log user in + template.clear_test_template_context() + self._setup(openid_plugin_app) + + @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) + @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) + def _login_user(): + openid_plugin_app.post( + '/auth/openid/login/finish/', { + 'openid': u'http://real.myopenid.com'}) + + _login_user() + + # Try and delete only OpenID url + template.clear_test_template_context() + res = openid_plugin_app.post( + '/edit/openid/delete/', { + 'openid': 'http://real.myopenid.com'}) + assert 'mediagoblin/plugins/openid/delete.html' in template.TEMPLATE_TEST_CONTEXT + + # Add OpenID to user + # Empty form + template.clear_test_template_context() + res = openid_plugin_app.post( + '/edit/openid/', {}) + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html'] + form = context['form'] + assert form.openid.errors == [u'This field is required.'] + + # Try with a bad url + template.clear_test_template_context() + openid_plugin_app.post( + '/edit/openid/', { + 'openid': u'not_a_url.com'}) + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html'] + form = context['form'] + assert form.openid.errors == [u'Please enter a valid url.'] + + # Try with a url that's already registered + template.clear_test_template_context() + openid_plugin_app.post( + '/edit/openid/', { + 'openid': 'http://real.myopenid.com'}) + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html'] + form = context['form'] + assert form.openid.errors == [u'Sorry, an account is already registered to that OpenID.'] + + # Test adding openid to account + # Need to clear_test_template_context before calling _setup + template.clear_test_template_context() + self._setup(openid_plugin_app, edit=True) + + # Need to remove openid_url from db because it was added at setup + openid = OpenIDUserURL.query.filter_by( + openid_url=u'http://add.myopenid.com') + openid.delete() + + @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) + @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) + def _test_add(): + # Successful add + template.clear_test_template_context() + res = openid_plugin_app.post( + '/edit/openid/', { + 'openid': u'http://add.myopenid.com'}) + res.follow() + + # Correct place? + assert urlparse.urlsplit(res.location)[2] == '/edit/account/' + assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT + + # OpenID Added? + new_openid = mg_globals.database.OpenIDUserURL.query.filter_by( + openid_url=u'http://add.myopenid.com').first() + assert new_openid + + _test_add() + + # Test deleting openid from account + # Need to clear_test_template_context before calling _setup + template.clear_test_template_context() + self._setup(openid_plugin_app, delete=True) + + # Need to add OpenID back to user because it was deleted during + # patch + openid = OpenIDUserURL() + openid.openid_url = 'http://add.myopenid.com' + openid.user_id = test_user.id + openid.save() + + @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) + @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) + def _test_delete(self, test_user): + # Delete openid from user + # Create another user to test deleting OpenID that doesn't belong to them + new_user = fixture_add_user(username='newman') + openid = OpenIDUserURL() + openid.openid_url = 'http://realfake.myopenid.com/' + openid.user_id = new_user.id + openid.save() + + # Try and delete OpenID url that isn't the users + template.clear_test_template_context() + res = openid_plugin_app.post( + '/edit/openid/delete/', { + 'openid': 'http://realfake.myopenid.com/'}) + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/delete.html'] + form = context['form'] + assert form.openid.errors == [u'That OpenID is not registered to this account.'] + + # Delete OpenID + # Kind of weird to POST to delete/finish + template.clear_test_template_context() + res = openid_plugin_app.post( + '/edit/openid/delete/finish/', { + 'openid': u'http://add.myopenid.com'}) + res.follow() + + # Correct place? + assert urlparse.urlsplit(res.location)[2] == '/edit/account/' + assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT + + # OpenID deleted? + new_openid = mg_globals.database.OpenIDUserURL.query.filter_by( + openid_url=u'http://add.myopenid.com').first() + assert not new_openid + + _test_delete(self, test_user) diff --git a/mediagoblin/tests/test_paste.ini b/mediagoblin/tests/test_paste.ini index 91ecbb84..a9595432 100644 --- a/mediagoblin/tests/test_paste.ini +++ b/mediagoblin/tests/test_paste.ini @@ -6,6 +6,8 @@ use = egg:Paste#urlmap / = mediagoblin /mgoblin_media/ = publicstore_serve /test_static/ = mediagoblin_static +/theme_static/ = theme_static +/plugin_static/ = plugin_static [app:mediagoblin] use = egg:mediagoblin#app @@ -13,12 +15,22 @@ config = %(here)s/mediagoblin.ini [app:publicstore_serve] use = egg:Paste#static -document_root = %(here)s/test_user_dev/media/public +document_root = %(here)s/user_dev/media/public [app:mediagoblin_static] use = egg:Paste#static document_root = %(here)s/mediagoblin/static/ +[app:theme_static] +use = egg:Paste#static +document_root = %(here)s/user_dev/theme_static/ +cache_max_age = 86400 + +[app:plugin_static] +use = egg:Paste#static +document_root = %(here)s/user_dev/plugin_static/ +cache_max_age = 86400 + [celery] CELERY_ALWAYS_EAGER = true diff --git a/mediagoblin/tests/test_persona.py b/mediagoblin/tests/test_persona.py new file mode 100644 index 00000000..a1cd30eb --- /dev/null +++ b/mediagoblin/tests/test_persona.py @@ -0,0 +1,214 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import urlparse +import pkg_resources +import pytest +import mock + +pytest.importorskip("requests") + +from mediagoblin import mg_globals +from mediagoblin.db.base import Session +from mediagoblin.db.models import Privilege +from mediagoblin.tests.tools import get_app +from mediagoblin.tools import template + + +# App with plugin enabled +@pytest.fixture() +def persona_plugin_app(request): + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'mediagoblin.tests.auth_configs', + 'persona_appconfig.ini')) + + +class TestPersonaPlugin(object): + def test_authentication_views(self, persona_plugin_app): + res = persona_plugin_app.get('/auth/login/') + + assert urlparse.urlsplit(res.location)[2] == '/' + + res = persona_plugin_app.get('/auth/register/') + + assert urlparse.urlsplit(res.location)[2] == '/' + + res = persona_plugin_app.get('/auth/persona/login/') + + assert urlparse.urlsplit(res.location)[2] == '/auth/login/' + + res = persona_plugin_app.get('/auth/persona/register/') + + assert urlparse.urlsplit(res.location)[2] == '/auth/login/' + + @mock.patch('mediagoblin.plugins.persona.views._get_response', mock.Mock(return_value=u'test@example.com')) + def _test_registration(): + # No register users + template.clear_test_template_context() + res = persona_plugin_app.post( + '/auth/persona/login/', {}) + + assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] + register_form = context['register_form'] + + assert register_form.email.data == u'test@example.com' + assert register_form.persona_email.data == u'test@example.com' + + template.clear_test_template_context() + res = persona_plugin_app.post( + '/auth/persona/register/', {}) + + assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] + register_form = context['register_form'] + + assert register_form.username.errors == [u'This field is required.'] + assert register_form.email.errors == [u'This field is required.'] + assert register_form.persona_email.errors == [u'This field is required.'] + + # Successful register + template.clear_test_template_context() + res = persona_plugin_app.post( + '/auth/persona/register/', + {'username': 'chris', + 'email': 'chris@example.com', + 'persona_email': 'test@example.com'}) + res.follow() + + assert urlparse.urlsplit(res.location)[2] == '/u/chris/' + assert 'mediagoblin/user_pages/user_nonactive.html' in template.TEMPLATE_TEST_CONTEXT + + # Try to register same Persona email address + template.clear_test_template_context() + res = persona_plugin_app.post( + '/auth/persona/register/', + {'username': 'chris1', + 'email': 'chris1@example.com', + 'persona_email': 'test@example.com'}) + + assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] + register_form = context['register_form'] + + assert register_form.persona_email.errors == [u'Sorry, an account is already registered to that Persona email.'] + + # Logout + persona_plugin_app.get('/auth/logout/') + + # Get user and detach from session + test_user = mg_globals.database.User.query.filter_by( + username=u'chris').first() + active_privilege = Privilege.query.filter( + Privilege.privilege_name==u'active').first() + test_user.all_privileges.append(active_privilege) + test_user.save() + test_user = mg_globals.database.User.query.filter_by( + username=u'chris').first() + Session.expunge(test_user) + + # Add another user for _test_edit_persona + persona_plugin_app.post( + '/auth/persona/register/', + {'username': 'chris1', + 'email': 'chris1@example.com', + 'persona_email': 'test1@example.com'}) + + # Log back in + template.clear_test_template_context() + res = persona_plugin_app.post( + '/auth/persona/login/') + res.follow() + + assert urlparse.urlsplit(res.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT + + # Make sure user is in the session + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] + session = context['request'].session + assert session['user_id'] == unicode(test_user.id) + + _test_registration() + + @mock.patch('mediagoblin.plugins.persona.views._get_response', mock.Mock(return_value=u'new@example.com')) + def _test_edit_persona(): + # Try and delete only Persona email address + template.clear_test_template_context() + res = persona_plugin_app.post( + '/edit/persona/', + {'email': 'test@example.com'}) + + assert 'mediagoblin/plugins/persona/edit.html' in template.TEMPLATE_TEST_CONTEXT + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/persona/edit.html'] + form = context['form'] + + assert form.email.errors == [u"You can't delete your only Persona email address unless you have a password set."] + + template.clear_test_template_context() + res = persona_plugin_app.post( + '/edit/persona/', {}) + + assert 'mediagoblin/plugins/persona/edit.html' in template.TEMPLATE_TEST_CONTEXT + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/persona/edit.html'] + form = context['form'] + + assert form.email.errors == [u'This field is required.'] + + # Try and delete Persona not owned by the user + template.clear_test_template_context() + res = persona_plugin_app.post( + '/edit/persona/', + {'email': 'test1@example.com'}) + + assert 'mediagoblin/plugins/persona/edit.html' in template.TEMPLATE_TEST_CONTEXT + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/persona/edit.html'] + form = context['form'] + + assert form.email.errors == [u'That Persona email address is not registered to this account.'] + + res = persona_plugin_app.get('/edit/persona/add/') + + assert urlparse.urlsplit(res.location)[2] == '/edit/persona/' + + # Add Persona email address + template.clear_test_template_context() + res = persona_plugin_app.post( + '/edit/persona/add/') + res.follow() + + assert urlparse.urlsplit(res.location)[2] == '/edit/account/' + + # Delete a Persona + res = persona_plugin_app.post( + '/edit/persona/', + {'email': 'test@example.com'}) + res.follow() + + assert urlparse.urlsplit(res.location)[2] == '/edit/account/' + + _test_edit_persona() + + @mock.patch('mediagoblin.plugins.persona.views._get_response', mock.Mock(return_value=u'test1@example.com')) + def _test_add_existing(): + template.clear_test_template_context() + res = persona_plugin_app.post( + '/edit/persona/add/') + res.follow() + + assert urlparse.urlsplit(res.location)[2] == '/edit/persona/' + + _test_add_existing() diff --git a/mediagoblin/tests/test_piwigo.py b/mediagoblin/tests/test_piwigo.py new file mode 100644 index 00000000..16ad0111 --- /dev/null +++ b/mediagoblin/tests/test_piwigo.py @@ -0,0 +1,71 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2013 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import pytest +from .tools import fixture_add_user + + +XML_PREFIX = "<?xml version='1.0' encoding='utf-8'?>\n" + + +class Test_PWG(object): + @pytest.fixture(autouse=True) + def setup(self, test_app): + self.test_app = test_app + + fixture_add_user() + + self.username = u"chris" + self.password = "toast" + + def do_post(self, method, params): + params["method"] = method + return self.test_app.post("/api/piwigo/ws.php", params) + + def do_get(self, method, params=None): + if params is None: + params = {} + params["method"] = method + return self.test_app.get("/api/piwigo/ws.php", params) + + def test_session(self): + resp = self.do_post("pwg.session.login", + {"username": u"nouser", "password": "wrong"}) + assert resp.body == XML_PREFIX \ + + '<rsp stat="fail"><err code="999" msg="Invalid username/password"/></rsp>' + + resp = self.do_post("pwg.session.login", + {"username": self.username, "password": "wrong"}) + assert resp.body == XML_PREFIX \ + + '<rsp stat="fail"><err code="999" msg="Invalid username/password"/></rsp>' + + resp = self.do_get("pwg.session.getStatus") + assert resp.body == XML_PREFIX \ + + '<rsp stat="ok"><username>guest</username></rsp>' + + resp = self.do_post("pwg.session.login", + {"username": self.username, "password": self.password}) + assert resp.body == XML_PREFIX + '<rsp stat="ok">1</rsp>' + + resp = self.do_get("pwg.session.getStatus") + assert resp.body == XML_PREFIX \ + + '<rsp stat="ok"><username>chris</username></rsp>' + + self.do_get("pwg.session.logout") + + resp = self.do_get("pwg.session.getStatus") + assert resp.body == XML_PREFIX \ + + '<rsp stat="ok"><username>guest</username></rsp>' diff --git a/mediagoblin/tests/test_pluginapi.py b/mediagoblin/tests/test_pluginapi.py index f03e868f..eae0ce15 100644 --- a/mediagoblin/tests/test_pluginapi.py +++ b/mediagoblin/tests/test_pluginapi.py @@ -14,14 +14,22 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import os +import json import sys from configobj import ConfigObj import pytest +import pkg_resources +from validate import VdtTypeError from mediagoblin import mg_globals from mediagoblin.init.plugins import setup_plugins +from mediagoblin.init.config import read_mediagoblin_config +from mediagoblin.gmg_commands.assetlink import link_plugin_assets from mediagoblin.tools import pluginapi +from mediagoblin.tests.tools import get_app +from mediagoblin.tools.common import CollectingPrinter def with_cleanup(*modules_to_delete): @@ -294,3 +302,165 @@ def test_hook_transform(): assert pluginapi.hook_transform( "expand_tuple", (-1, 0)) == (-1, 0, 1, 2, 3) + + +def test_plugin_config(): + """ + Make sure plugins can set up their own config + """ + config, validation_result = read_mediagoblin_config( + pkg_resources.resource_filename( + 'mediagoblin.tests', 'appconfig_plugin_specs.ini')) + + pluginspec_section = config['plugins'][ + 'mediagoblin.tests.testplugins.pluginspec'] + assert pluginspec_section['some_string'] == 'not blork' + assert pluginspec_section['dont_change_me'] == 'still the default' + + # Make sure validation works... this should be an error + assert isinstance( + validation_result[ + 'plugins'][ + 'mediagoblin.tests.testplugins.pluginspec'][ + 'some_int'], + VdtTypeError) + + # the callables thing shouldn't really have anything though. + assert len(config['plugins'][ + 'mediagoblin.tests.testplugins.callables1']) == 0 + + +@pytest.fixture() +def context_modified_app(request): + """ + Get a MediaGoblin app fixture using appconfig_context_modified.ini + """ + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'mediagoblin.tests', 'appconfig_context_modified.ini')) + + +def test_modify_context(context_modified_app): + """ + Test that we can modify both the view/template specific and + global contexts for templates. + """ + # Specific thing passed into a page + result = context_modified_app.get("/modify_context/specific/") + assert result.body.strip() == """Specific page! + +specific thing: in yer specificpage +global thing: globally appended! +something: orother +doubleme: happyhappy""" + + # General test, should have global context variable only + result = context_modified_app.get("/modify_context/") + assert result.body.strip() == """General page! + +global thing: globally appended! +lol: cats +doubleme: joyjoy""" + + +@pytest.fixture() +def static_plugin_app(request): + """ + Get a MediaGoblin app fixture using appconfig_static_plugin.ini + """ + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'mediagoblin.tests', 'appconfig_static_plugin.ini')) + + +def test_plugin_assetlink(static_plugin_app): + """ + Test that the assetlink command works correctly + """ + linked_assets_dir = mg_globals.app_config['plugin_linked_assets_dir'] + plugin_link_dir = os.path.join( + linked_assets_dir.rstrip(os.path.sep), + 'staticstuff') + + plugin_statics = pluginapi.hook_runall("static_setup") + assert len(plugin_statics) == 1 + plugin_static = plugin_statics[0] + + def run_assetlink(): + printer = CollectingPrinter() + + link_plugin_assets( + plugin_static, linked_assets_dir, printer) + + return printer + + # it shouldn't exist yet + assert not os.path.lexists(plugin_link_dir) + + # link dir doesn't exist, link it + result = run_assetlink().collection[0] + assert result == \ + 'Linked asset directory for plugin "staticstuff":\n %s\nto:\n %s\n' % ( + plugin_static.file_path.rstrip(os.path.sep), + plugin_link_dir) + assert os.path.lexists(plugin_link_dir) + assert os.path.islink(plugin_link_dir) + assert os.path.realpath(plugin_link_dir) == plugin_static.file_path + + # link dir exists, leave it alone + # (and it should exist still since we just ran it..) + result = run_assetlink().collection[0] + assert result == 'Skipping "staticstuff"; already set up.\n' + assert os.path.lexists(plugin_link_dir) + assert os.path.islink(plugin_link_dir) + assert os.path.realpath(plugin_link_dir) == plugin_static.file_path + + # link dir exists, is a symlink to somewhere else (re-link) + junk_file_path = os.path.join( + linked_assets_dir.rstrip(os.path.sep), + 'junk.txt') + with file(junk_file_path, 'w') as junk_file: + junk_file.write('barf') + + os.unlink(plugin_link_dir) + os.symlink(junk_file_path, plugin_link_dir) + + result = run_assetlink().combined_string + assert result == """Old link found for "staticstuff"; removing. +Linked asset directory for plugin "staticstuff": + %s +to: + %s +""" % (plugin_static.file_path.rstrip(os.path.sep), plugin_link_dir) + assert os.path.lexists(plugin_link_dir) + assert os.path.islink(plugin_link_dir) + assert os.path.realpath(plugin_link_dir) == plugin_static.file_path + + # link dir exists, but is a non-symlink + os.unlink(plugin_link_dir) + with file(plugin_link_dir, 'w') as clobber_file: + clobber_file.write('clobbered!') + + result = run_assetlink().collection[0] + assert result == 'Could not link "staticstuff": %s exists and is not a symlink\n' % ( + plugin_link_dir) + + with file(plugin_link_dir, 'r') as clobber_file: + assert clobber_file.read() == 'clobbered!' + + +def test_plugin_staticdirect(static_plugin_app): + """ + Test that the staticdirect utilities pull up the right things + """ + result = json.loads( + static_plugin_app.get('/staticstuff/').body) + + assert len(result) == 2 + + assert result['mgoblin_bunny_pic'] == '/test_static/images/bunny_pic.png' + assert result['plugin_bunny_css'] == \ + '/plugin_static/staticstuff/css/bunnify.css' + diff --git a/mediagoblin/tests/test_privileges.py b/mediagoblin/tests/test_privileges.py new file mode 100644 index 00000000..05829b34 --- /dev/null +++ b/mediagoblin/tests/test_privileges.py @@ -0,0 +1,205 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import pytest +from datetime import date, timedelta +from webtest import AppError + +from mediagoblin.tests.tools import fixture_add_user, fixture_media_entry + +from mediagoblin.db.models import User, UserBan +from mediagoblin.tools import template + +from .resources import GOOD_JPG + +class TestPrivilegeFunctionality: + + @pytest.fixture(autouse=True) + def _setup(self, test_app): + self.test_app = test_app + + fixture_add_user(u'alex', + privileges=[u'admin',u'active']) + fixture_add_user(u'meow', + privileges=[u'moderator',u'active',u'reporter']) + fixture_add_user(u'natalie', + privileges=[u'active']) + self.query_for_users() + + def login(self, username): + self.test_app.post( + '/auth/login/', { + 'username': username, + 'password': 'toast'}) + self.query_for_users() + + def logout(self): + self.test_app.get('/auth/logout/') + self.query_for_users() + + def do_post(self, data, *context_keys, **kwargs): + url = kwargs.pop('url', '/submit/') + do_follow = kwargs.pop('do_follow', False) + template.clear_test_template_context() + response = self.test_app.post(url, data, **kwargs) + if do_follow: + response.follow() + context_data = template.TEMPLATE_TEST_CONTEXT + for key in context_keys: + context_data = context_data[key] + return response, context_data + + def query_for_users(self): + self.admin_user = User.query.filter(User.username==u'alex').first() + self.mod_user = User.query.filter(User.username==u'meow').first() + self.user = User.query.filter(User.username==u'natalie').first() + + def testUserBanned(self): + self.login(u'natalie') + uid = self.user.id + # First, test what happens when a user is banned indefinitely + #---------------------------------------------------------------------- + user_ban = UserBan(user_id=uid, + reason=u'Testing whether user is banned', + expiration_date=None) + user_ban.save() + + response = self.test_app.get('/') + assert response.status == "200 OK" + assert "You are Banned" in response.body + # Then test what happens when that ban has an expiration date which + # hasn't happened yet + #---------------------------------------------------------------------- + user_ban = UserBan.query.get(uid) + user_ban.delete() + user_ban = UserBan(user_id=uid, + reason=u'Testing whether user is banned', + expiration_date= date.today() + timedelta(days=20)) + user_ban.save() + + response = self.test_app.get('/') + assert response.status == "200 OK" + assert "You are Banned" in response.body + + # Then test what happens when that ban has an expiration date which + # has already happened + #---------------------------------------------------------------------- + user_ban = UserBan.query.get(uid) + user_ban.delete() + exp_date = date.today() - timedelta(days=20) + user_ban = UserBan(user_id=uid, + reason=u'Testing whether user is banned', + expiration_date= exp_date) + user_ban.save() + + response = self.test_app.get('/') + assert response.status == "302 FOUND" + assert not "You are Banned" in response.body + + def testVariousPrivileges(self): + # The various actions that require privileges (ex. reporting, + # commenting, moderating...) are tested in other tests. This method + # will be used to ensure that those actions are impossible for someone + # without the proper privileges. + # For other tests that show what happens when a user has the proper + # privileges, check out: + # tests/test_moderation.py moderator + # tests/test_notifications.py commenter + # tests/test_reporting.py reporter + # tests/test_submission.py uploader + #---------------------------------------------------------------------- + self.login(u'natalie') + + # First test the get and post requests of submission/uploading + #---------------------------------------------------------------------- + with pytest.raises(AppError) as excinfo: + response = self.test_app.get('/submit/') + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + + with pytest.raises(AppError) as excinfo: + response = self.do_post({'upload_files':[('file',GOOD_JPG)], + 'title':u'Normal Upload 1'}, + url='/submit/') + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + # Test that a user cannot comment without the commenter privilege + #---------------------------------------------------------------------- + self.query_for_users() + + media_entry = fixture_media_entry(uploader=self.admin_user.id, + state=u'processed') + + media_entry_id = media_entry.id + media_uri_id = '/u/{0}/m/{1}/'.format(self.admin_user.username, + media_entry.id) + media_uri_slug = '/u/{0}/m/{1}/'.format(self.admin_user.username, + media_entry.slug) + response = self.test_app.get(media_uri_slug) + assert not "Add a comment" in response.body + + self.query_for_users() + with pytest.raises(AppError) as excinfo: + response = self.test_app.post( + media_uri_id + 'comment/add/', + {'comment_content': u'Test comment #42'}) + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + # Test that a user cannot report without the reporter privilege + #---------------------------------------------------------------------- + with pytest.raises(AppError) as excinfo: + response = self.test_app.get(media_uri_slug+"report/") + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + with pytest.raises(AppError) as excinfo: + response = self.do_post( + {'report_reason':u'Testing Reports #1', + 'reporter_id':u'3'}, + url=(media_uri_slug+"report/")) + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + # Test that a user cannot access the moderation pages w/o moderator + # or admin privileges + #---------------------------------------------------------------------- + with pytest.raises(AppError) as excinfo: + response = self.test_app.get("/mod/users/") + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + with pytest.raises(AppError) as excinfo: + response = self.test_app.get("/mod/reports/") + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + with pytest.raises(AppError) as excinfo: + response = self.test_app.get("/mod/media/") + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + with pytest.raises(AppError) as excinfo: + response = self.test_app.get("/mod/users/1/") + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + with pytest.raises(AppError) as excinfo: + response = self.test_app.get("/mod/reports/1/") + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) + + self.query_for_users() + + with pytest.raises(AppError) as excinfo: + response, context = self.do_post({'action_to_resolve':[u'takeaway'], + 'take_away_privileges':[u'active'], + 'targeted_user':self.admin_user.id}, + url='/mod/reports/1/') + self.query_for_users() + assert 'Bad response: 403 FORBIDDEN' in str(excinfo) diff --git a/mediagoblin/tests/test_processing.py b/mediagoblin/tests/test_processing.py index fe8489aa..591add96 100644 --- a/mediagoblin/tests/test_processing.py +++ b/mediagoblin/tests/test_processing.py @@ -1,7 +1,5 @@ #!/usr/bin/env python -from nose.tools import assert_equal - from mediagoblin import processing class TestProcessing(object): @@ -10,7 +8,7 @@ class TestProcessing(object): result = builder.fill(format) if output is None: return result - assert_equal(output, result) + assert output == result def test_easy_filename_fill(self): self.run_fill('/home/user/foo.TXT', '{basename}bar{ext}', 'foobar.txt') diff --git a/mediagoblin/tests/test_reporting.py b/mediagoblin/tests/test_reporting.py new file mode 100644 index 00000000..a154a061 --- /dev/null +++ b/mediagoblin/tests/test_reporting.py @@ -0,0 +1,167 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import pytest + +from mediagoblin.tools import template +from mediagoblin.tests.tools import (fixture_add_user, fixture_media_entry, + fixture_add_comment, fixture_add_comment_report) +from mediagoblin.db.models import (MediaReport, CommentReport, User, + MediaComment) + + +class TestReportFiling: + @pytest.fixture(autouse=True) + def _setup(self, test_app): + self.test_app = test_app + + fixture_add_user(u'allie', + privileges=[u'reporter',u'active']) + fixture_add_user(u'natalie', + privileges=[u'active', u'moderator']) + + def login(self, username): + self.test_app.post( + '/auth/login/', { + 'username': username, + 'password': 'toast'}) + + def logout(self): + self.test_app.get('/auth/logout/') + + def do_post(self, data, *context_keys, **kwargs): + url = kwargs.pop('url', '/submit/') + do_follow = kwargs.pop('do_follow', False) + template.clear_test_template_context() + response = self.test_app.post(url, data, **kwargs) + if do_follow: + response.follow() + context_data = template.TEMPLATE_TEST_CONTEXT + for key in context_keys: + context_data = context_data[key] + return response, context_data + + def query_for_users(self): + return (User.query.filter(User.username==u'allie').first(), + User.query.filter(User.username==u'natalie').first()) + + def testMediaReports(self): + self.login(u'allie') + allie_user, natalie_user = self.query_for_users() + allie_id = allie_user.id + + media_entry = fixture_media_entry(uploader=natalie_user.id, + state=u'processed') + + mid = media_entry.id + media_uri_slug = '/u/{0}/m/{1}/'.format(natalie_user.username, + media_entry.slug) + + response = self.test_app.get(media_uri_slug + "report/") + assert response.status == "200 OK" + + response, context = self.do_post( + {'report_reason':u'Testing Media Report', + 'reporter_id':unicode(allie_id)},url= media_uri_slug + "report/") + + assert response.status == "302 FOUND" + + media_report = MediaReport.query.first() + + allie_user, natalie_user = self.query_for_users() + assert media_report is not None + assert media_report.report_content == u'Testing Media Report' + assert media_report.reporter_id == allie_id + assert media_report.reported_user_id == natalie_user.id + assert media_report.created is not None + assert media_report.discriminator == 'media_report' + + def testCommentReports(self): + self.login(u'allie') + allie_user, natalie_user = self.query_for_users() + allie_id = allie_user.id + + media_entry = fixture_media_entry(uploader=natalie_user.id, + state=u'processed') + mid = media_entry.id + fixture_add_comment(media_entry=mid, + author=natalie_user.id) + comment = MediaComment.query.first() + + comment_uri_slug = '/u/{0}/m/{1}/c/{2}/'.format(natalie_user.username, + media_entry.slug, + comment.id) + + response = self.test_app.get(comment_uri_slug + "report/") + assert response.status == "200 OK" + + response, context = self.do_post({ + 'report_reason':u'Testing Comment Report', + 'reporter_id':unicode(allie_id)},url= comment_uri_slug + "report/") + + assert response.status == "302 FOUND" + + comment_report = CommentReport.query.first() + + allie_user, natalie_user = self.query_for_users() + assert comment_report is not None + assert comment_report.report_content == u'Testing Comment Report' + assert comment_report.reporter_id == allie_id + assert comment_report.reported_user_id == natalie_user.id + assert comment_report.created is not None + assert comment_report.discriminator == 'comment_report' + + def testArchivingReports(self): + self.login(u'natalie') + allie_user, natalie_user = self.query_for_users() + allie_id, natalie_id = allie_user.id, natalie_user.id + + fixture_add_comment(author=allie_user.id, + comment=u'Comment will be removed') + test_comment = MediaComment.query.filter( + MediaComment.author==allie_user.id).first() + fixture_add_comment_report(comment=test_comment, + reported_user=allie_user, + report_content=u'Testing Archived Reports #1', + reporter=natalie_user) + comment_report = CommentReport.query.filter( + CommentReport.reported_user==allie_user).first() + + assert comment_report.report_content == u'Testing Archived Reports #1' + response, context = self.do_post( + {'action_to_resolve':[u'userban', u'delete'], + 'targeted_user':allie_user.id, + 'resolution_content':u'This is a test of archiving reports.'}, + url='/mod/reports/{0}/'.format(comment_report.id)) + + assert response.status == "302 FOUND" + allie_user, natalie_user = self.query_for_users() + + archived_report = CommentReport.query.filter( + CommentReport.reported_user==allie_user).first() + + assert CommentReport.query.count() != 0 + assert archived_report is not None + assert archived_report.report_content == u'Testing Archived Reports #1' + assert archived_report.reporter_id == natalie_id + assert archived_report.reported_user_id == allie_id + assert archived_report.created is not None + assert archived_report.resolved is not None + assert archived_report.result == u'''This is a test of archiving reports. +natalie banned user allie indefinitely. +natalie deleted the comment.''' + assert archived_report.discriminator == 'comment_report' + diff --git a/mediagoblin/tests/test_sql_migrations.py b/mediagoblin/tests/test_sql_migrations.py index 2fc4c043..3d67fdf6 100644 --- a/mediagoblin/tests/test_sql_migrations.py +++ b/mediagoblin/tests/test_sql_migrations.py @@ -58,6 +58,10 @@ class Level1(Base1): SET1_MODELS = [Creature1, Level1] +FOUNDATIONS = {Creature1:[{'name':u'goblin','num_legs':2,'is_demon':False}, + {'name':u'cerberus','num_legs':4,'is_demon':True}] + } + SET1_MIGRATIONS = {} ####################################################### @@ -542,7 +546,6 @@ def _insert_migration3_objects(session): session.commit() - def create_test_engine(): from sqlalchemy import create_engine engine = create_engine('sqlite:///:memory:', echo=False) @@ -572,7 +575,7 @@ def test_set1_to_set3(): printer = CollectingPrinter() migration_manager = MigrationManager( - u'__main__', SET1_MODELS, SET1_MIGRATIONS, Session(), + u'__main__', SET1_MODELS, FOUNDATIONS, SET1_MIGRATIONS, Session(), printer) # Check latest migration and database current migration @@ -585,11 +588,13 @@ def test_set1_to_set3(): assert result == u'inited' # Check output assert printer.combined_string == ( - "-> Initializing main mediagoblin tables... done.\n") + "-> Initializing main mediagoblin tables... done.\n" + \ + " + Laying foundations for Creature1 table\n" ) # Check version in database assert migration_manager.latest_migration == 0 assert migration_manager.database_current_migration == 0 + # Install the initial set # ----------------------- @@ -597,8 +602,8 @@ def test_set1_to_set3(): # Try to "re-migrate" with same manager settings... nothing should happen migration_manager = MigrationManager( - u'__main__', SET1_MODELS, SET1_MIGRATIONS, Session(), - printer) + u'__main__', SET1_MODELS, FOUNDATIONS, SET1_MIGRATIONS, + Session(), printer) assert migration_manager.init_or_migrate() == None # Check version in database @@ -639,6 +644,20 @@ def test_set1_to_set3(): # Now check to see if stuff seems to be in there. session = Session() + # Check the creation of the foundation rows on the creature table + creature = session.query(Creature1).filter_by( + name=u'goblin').one() + assert creature.num_legs == 2 + assert creature.is_demon == False + + creature = session.query(Creature1).filter_by( + name=u'cerberus').one() + assert creature.num_legs == 4 + assert creature.is_demon == True + + + # Check the creation of the inserted rows on the creature and levels tables + creature = session.query(Creature1).filter_by( name=u'centipede').one() assert creature.num_legs == 100 @@ -679,7 +698,7 @@ def test_set1_to_set3(): # isn't said to be updated yet printer = CollectingPrinter() migration_manager = MigrationManager( - u'__main__', SET3_MODELS, SET3_MIGRATIONS, Session(), + u'__main__', SET3_MODELS, FOUNDATIONS, SET3_MIGRATIONS, Session(), printer) assert migration_manager.latest_migration == 8 @@ -706,7 +725,7 @@ def test_set1_to_set3(): # Make sure version matches expected migration_manager = MigrationManager( - u'__main__', SET3_MODELS, SET3_MIGRATIONS, Session(), + u'__main__', SET3_MODELS, FOUNDATIONS, SET3_MIGRATIONS, Session(), printer) assert migration_manager.latest_migration == 8 assert migration_manager.database_current_migration == 8 @@ -772,6 +791,15 @@ def test_set1_to_set3(): # Now check to see if stuff seems to be in there. session = Session() + + + # Start with making sure that the foundations did not run again + assert session.query(Creature3).filter_by( + name=u'goblin').count() == 1 + assert session.query(Creature3).filter_by( + name=u'cerberus').count() == 1 + + # Then make sure the models have been migrated correctly creature = session.query(Creature3).filter_by( name=u'centipede').one() assert creature.num_limbs == 100.0 diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py index 162b2d19..b5b13ed3 100644 --- a/mediagoblin/tests/test_submission.py +++ b/mediagoblin/tests/test_submission.py @@ -24,13 +24,14 @@ import pytest from mediagoblin.tests.tools import fixture_add_user from mediagoblin import mg_globals -from mediagoblin.db.models import MediaEntry +from mediagoblin.db.models import MediaEntry, User +from mediagoblin.db.base import Session from mediagoblin.tools import template -from mediagoblin.media_types.image import MEDIA_MANAGER as img_MEDIA_MANAGER +from mediagoblin.media_types.image import ImageMediaManager from mediagoblin.media_types.pdf.processing import check_prerequisites as pdf_check_prerequisites from .resources import GOOD_JPG, GOOD_PNG, EVIL_FILE, EVIL_JPG, EVIL_PNG, \ - BIG_BLUE, GOOD_PDF, GPS_JPG + BIG_BLUE, GOOD_PDF, GPS_JPG, MED_PNG, BIG_PNG GOOD_TAG_STRING = u'yin,yang' BAD_TAG_STRING = unicode('rage,' + 'f' * 26 + 'u' * 26) @@ -46,12 +47,22 @@ class TestSubmission: # TODO: Possibly abstract into a decorator like: # @as_authenticated_user('chris') - test_user = fixture_add_user() - - self.test_user = test_user + fixture_add_user(privileges=[u'active',u'uploader', u'commenter']) self.login() + def our_user(self): + """ + Fetch the user we're submitting with. Every .get() or .post() + invalidates the session; this is a hacky workaround. + """ + #### FIXME: Pytest collects this as a test and runs this. + #### ... it shouldn't. At least it passes, but that's + #### totally stupid. + #### Also if we found a way to make this run it should be a + #### property. + return User.query.filter(User.username==u'chris').first() + def login(self): self.test_app.post( '/auth/login/', { @@ -77,7 +88,7 @@ class TestSubmission: return {'upload_files': [('file', filename)]} def check_comments(self, request, media_id, count): - comments = request.db.MediaComment.find({'media_entry': media_id}) + comments = request.db.MediaComment.query.filter_by(media_entry=media_id) assert count == len(list(comments)) def test_missing_fields(self): @@ -97,19 +108,40 @@ class TestSubmission: def check_normal_upload(self, title, filename): response, context = self.do_post({'title': title}, do_follow=True, **self.upload_data(filename)) - self.check_url(response, '/u/{0}/'.format(self.test_user.username)) + self.check_url(response, '/u/{0}/'.format(self.our_user().username)) assert 'mediagoblin/user_pages/user.html' in context # Make sure the media view is at least reachable, logged in... - url = '/u/{0}/m/{1}/'.format(self.test_user.username, + url = '/u/{0}/m/{1}/'.format(self.our_user().username, title.lower().replace(' ', '-')) self.test_app.get(url) # ... and logged out too. self.logout() self.test_app.get(url) + def user_upload_limits(self, uploaded=None, upload_limit=None): + our_user = self.our_user() + + if uploaded: + our_user.uploaded = uploaded + if upload_limit: + our_user.upload_limit = upload_limit + + our_user.save() + Session.expunge(our_user) + def test_normal_jpg(self): + # User uploaded should be 0 + assert self.our_user().uploaded == 0 + self.check_normal_upload(u'Normal upload 1', GOOD_JPG) + # User uploaded should be the same as GOOD_JPG size in Mb + file_size = os.stat(GOOD_JPG).st_size / (1024.0 * 1024) + file_size = float('{0:.2f}'.format(file_size)) + + # Reload user + assert self.our_user().uploaded == file_size + def test_normal_png(self): self.check_normal_upload(u'Normal upload 2', GOOD_PNG) @@ -118,11 +150,65 @@ class TestSubmission: response, context = self.do_post({'title': u'Normal upload 3 (pdf)'}, do_follow=True, **self.upload_data(GOOD_PDF)) - self.check_url(response, '/u/{0}/'.format(self.test_user.username)) + self.check_url(response, '/u/{0}/'.format(self.our_user().username)) + assert 'mediagoblin/user_pages/user.html' in context + + def test_default_upload_limits(self): + self.user_upload_limits(uploaded=500) + + # User uploaded should be 500 + assert self.our_user().uploaded == 500 + + response, context = self.do_post({'title': u'Normal upload 4'}, + do_follow=True, + **self.upload_data(GOOD_JPG)) + self.check_url(response, '/u/{0}/'.format(self.our_user().username)) assert 'mediagoblin/user_pages/user.html' in context + # Shouldn't have uploaded + assert self.our_user().uploaded == 500 + + def test_user_upload_limit(self): + self.user_upload_limits(uploaded=25, upload_limit=25) + + # User uploaded should be 25 + assert self.our_user().uploaded == 25 + + response, context = self.do_post({'title': u'Normal upload 5'}, + do_follow=True, + **self.upload_data(GOOD_JPG)) + self.check_url(response, '/u/{0}/'.format(self.our_user().username)) + assert 'mediagoblin/user_pages/user.html' in context + + # Shouldn't have uploaded + assert self.our_user().uploaded == 25 + + def test_user_under_limit(self): + self.user_upload_limits(uploaded=499) + + # User uploaded should be 499 + assert self.our_user().uploaded == 499 + + response, context = self.do_post({'title': u'Normal upload 6'}, + do_follow=False, + **self.upload_data(MED_PNG)) + form = context['mediagoblin/submit/start.html']['submit_form'] + assert form.file.errors == [u'Sorry, uploading this file will put you' + ' over your upload limit.'] + + # Shouldn't have uploaded + assert self.our_user().uploaded == 499 + + def test_big_file(self): + response, context = self.do_post({'title': u'Normal upload 7'}, + do_follow=False, + **self.upload_data(BIG_PNG)) + + form = context['mediagoblin/submit/start.html']['submit_form'] + assert form.file.errors == [u'Sorry, the file size is too big.'] + def check_media(self, request, find_data, count=None): - media = MediaEntry.find(find_data) + media = MediaEntry.query.filter_by(**find_data) if count is not None: assert media.count() == count if count == 0: @@ -155,6 +241,7 @@ class TestSubmission: 'ffffffffffffffffffffffffffuuuuuuuuuuuuuuuuuuuuuuuuuu'] def test_delete(self): + self.user_upload_limits(uploaded=50) response, request = self.do_post({'title': u'Balanced Goblin'}, *REQUEST_CONTEXT, do_follow=True, **self.upload_data(GOOD_JPG)) @@ -164,7 +251,7 @@ class TestSubmission: # render and post to the edit page. edit_url = request.urlgen( 'mediagoblin.edit.edit_media', - user=self.test_user.username, media_id=media_id) + user=self.our_user().username, media_id=media_id) self.test_app.get(edit_url) self.test_app.post(edit_url, {'title': u'Balanced Goblin', @@ -177,7 +264,7 @@ class TestSubmission: self.check_comments(request, media_id, 0) comment_url = request.urlgen( 'mediagoblin.user_pages.media_post_comment', - user=self.test_user.username, media_id=media_id) + user=self.our_user().username, media_id=media_id) response = self.do_post({'comment_content': 'i love this test'}, url=comment_url, do_follow=True)[0] self.check_comments(request, media_id, 1) @@ -186,7 +273,7 @@ class TestSubmission: # --------------------------------------------------- delete_url = request.urlgen( 'mediagoblin.user_pages.media_confirm_delete', - user=self.test_user.username, media_id=media_id) + user=self.our_user().username, media_id=media_id) # Empty data means don't confirm response = self.do_post({}, do_follow=True, url=delete_url)[0] media = self.check_media(request, {'title': u'Balanced Goblin'}, 1) @@ -199,6 +286,9 @@ class TestSubmission: self.check_media(request, {'id': media_id}, 0) self.check_comments(request, media_id, 0) + # Check that user.uploaded is the same as before the upload + assert self.our_user().uploaded == 50 + def test_evil_file(self): # Test non-suppoerted file with non-supported extension # ----------------------------------------------------- @@ -219,7 +309,7 @@ class TestSubmission: media = self.check_media(request, {'title': u'Balanced Goblin'}, 1) assert media.media_type == u'mediagoblin.media_types.image' - assert isinstance(media.media_manager, img_MEDIA_MANAGER) + assert isinstance(media.media_manager, ImageMediaManager) assert media.media_manager.entry == media @@ -240,8 +330,8 @@ class TestSubmission: request = context['request'] - media = request.db.MediaEntry.find_one({ - u'title': u'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE'}) + media = request.db.MediaEntry.query.filter_by( + title=u'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE').first() assert media.media_type == 'mediagoblin.media_types.image' @@ -251,8 +341,8 @@ class TestSubmission: # they'll be caught as failures during the processing step. response, context = self.do_post({'title': title}, do_follow=True, **self.upload_data(filename)) - self.check_url(response, '/u/{0}/'.format(self.test_user.username)) - entry = mg_globals.database.MediaEntry.find_one({'title': title}) + self.check_url(response, '/u/{0}/'.format(self.our_user().username)) + entry = mg_globals.database.MediaEntry.query.filter_by(title=title).first() assert entry.state == 'failed' assert entry.fail_error == u'mediagoblin.processing:BadMediaFail' diff --git a/mediagoblin/tests/test_submission/COPYING.txt b/mediagoblin/tests/test_submission/COPYING.txt new file mode 100644 index 00000000..3818aae4 --- /dev/null +++ b/mediagoblin/tests/test_submission/COPYING.txt @@ -0,0 +1,5 @@ +Images located in this directory tree are released under a GPLv3 license +and CC BY-SA 3.0 license. To the extent possible under law, the author(s) +have dedicated all copyright and related and neighboring rights to these +files to the public domain worldwide. These files are distributed without +any warranty. diff --git a/mediagoblin/tests/test_submission/big.png b/mediagoblin/tests/test_submission/big.png Binary files differnew file mode 100644 index 00000000..a284cfda --- /dev/null +++ b/mediagoblin/tests/test_submission/big.png diff --git a/mediagoblin/tests/test_submission/medium.png b/mediagoblin/tests/test_submission/medium.png Binary files differnew file mode 100644 index 00000000..e8b9ca00 --- /dev/null +++ b/mediagoblin/tests/test_submission/medium.png diff --git a/mediagoblin/tests/testplugins/modify_context/__init__.py b/mediagoblin/tests/testplugins/modify_context/__init__.py new file mode 100644 index 00000000..164e66c1 --- /dev/null +++ b/mediagoblin/tests/testplugins/modify_context/__init__.py @@ -0,0 +1,55 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.tools import pluginapi +import pkg_resources + + +def append_to_specific_context(context): + context['specific_page_append'] = 'in yer specificpage' + return context + +def append_to_global_context(context): + context['global_append'] = 'globally appended!' + return context + +def double_doubleme(context): + if 'doubleme' in context: + context['doubleme'] = context['doubleme'] * 2 + return context + + +def setup_plugin(): + routes = [ + ('modify_context.specific_page', + '/modify_context/specific/', + 'mediagoblin.tests.testplugins.modify_context.views:specific'), + ('modify_context.general_page', + '/modify_context/', + 'mediagoblin.tests.testplugins.modify_context.views:general')] + + pluginapi.register_routes(routes) + pluginapi.register_template_path( + pkg_resources.resource_filename( + 'mediagoblin.tests.testplugins.modify_context', 'templates')) + + +hooks = { + 'setup': setup_plugin, + ('modify_context.specific_page', + 'contextplugin/specific.html'): append_to_specific_context, + 'template_global_context': append_to_global_context, + 'template_context_prerender': double_doubleme} diff --git a/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/general.html b/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/general.html new file mode 100644 index 00000000..9cf96d3e --- /dev/null +++ b/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/general.html @@ -0,0 +1,5 @@ +General page! + +global thing: {{ global_append }} +lol: {{ lol }} +doubleme: {{ doubleme }} diff --git a/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/specific.html b/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/specific.html new file mode 100644 index 00000000..5b1b4c4a --- /dev/null +++ b/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/specific.html @@ -0,0 +1,6 @@ +Specific page! + +specific thing: {{ specific_page_append }} +global thing: {{ global_append }} +something: {{ something }} +doubleme: {{ doubleme }} diff --git a/mediagoblin/tests/testplugins/modify_context/views.py b/mediagoblin/tests/testplugins/modify_context/views.py new file mode 100644 index 00000000..701ec6f9 --- /dev/null +++ b/mediagoblin/tests/testplugins/modify_context/views.py @@ -0,0 +1,33 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.tools.response import render_to_response + + +def specific(request): + return render_to_response( + request, + 'contextplugin/specific.html', + {"something": "orother", + "doubleme": "happy"}) + + +def general(request): + return render_to_response( + request, + 'contextplugin/general.html', + {"lol": "cats", + "doubleme": "joy"}) diff --git a/mediagoblin/tests/testplugins/pluginspec/__init__.py b/mediagoblin/tests/testplugins/pluginspec/__init__.py new file mode 100644 index 00000000..76ca2b1f --- /dev/null +++ b/mediagoblin/tests/testplugins/pluginspec/__init__.py @@ -0,0 +1,22 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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/>. + +def setup_plugin(): + pass + +hooks = { + 'setup': setup_plugin, +} diff --git a/mediagoblin/tests/testplugins/pluginspec/config_spec.ini b/mediagoblin/tests/testplugins/pluginspec/config_spec.ini new file mode 100644 index 00000000..5c9c3bd7 --- /dev/null +++ b/mediagoblin/tests/testplugins/pluginspec/config_spec.ini @@ -0,0 +1,4 @@ +[plugin_spec] +some_string = string(default="blork") +some_int = integer(default=50) +dont_change_me = string(default="still the default")
\ No newline at end of file diff --git a/mediagoblin/tests/testplugins/staticstuff/__init__.py b/mediagoblin/tests/testplugins/staticstuff/__init__.py new file mode 100644 index 00000000..a2591646 --- /dev/null +++ b/mediagoblin/tests/testplugins/staticstuff/__init__.py @@ -0,0 +1,36 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.tools.staticdirect import PluginStatic +from mediagoblin.tools import pluginapi +from pkg_resources import resource_filename + +def setup_plugin(): + routes = [ + ('staticstuff.static_demo', + '/staticstuff/', + 'mediagoblin.tests.testplugins.staticstuff.views:static_demo')] + + pluginapi.register_routes(routes) + + +hooks = { + 'setup': setup_plugin, + 'static_setup': lambda: PluginStatic( + 'staticstuff', + resource_filename( + 'mediagoblin.tests.testplugins.staticstuff', + 'static'))} diff --git a/mediagoblin/tests/testplugins/staticstuff/static/css/bunnify.css b/mediagoblin/tests/testplugins/staticstuff/static/css/bunnify.css new file mode 100644 index 00000000..1294ab8a --- /dev/null +++ b/mediagoblin/tests/testplugins/staticstuff/static/css/bunnify.css @@ -0,0 +1,4 @@ +body { + background-color: #5edcf1; + color: #eb8add; +}
\ No newline at end of file diff --git a/mediagoblin/tests/testplugins/staticstuff/views.py b/mediagoblin/tests/testplugins/staticstuff/views.py new file mode 100644 index 00000000..34a5e8cb --- /dev/null +++ b/mediagoblin/tests/testplugins/staticstuff/views.py @@ -0,0 +1,28 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import json + +from werkzeug import Response + + +def static_demo(request): + return Response(json.dumps({ + # this does not exist, but we'll pretend it does ;) + 'mgoblin_bunny_pic': request.staticdirect( + 'images/bunny_pic.png'), + 'plugin_bunny_css': request.staticdirect( + 'css/bunnify.css', 'staticstuff')})) diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py index 52635e18..060dfda9 100644 --- a/mediagoblin/tests/tools.py +++ b/mediagoblin/tests/tools.py @@ -15,25 +15,25 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. -import sys import os import pkg_resources import shutil -from functools import wraps from paste.deploy import loadapp from webtest import TestApp from mediagoblin import mg_globals -from mediagoblin.db.models import User, MediaEntry, Collection +from mediagoblin.db.models import User, MediaEntry, Collection, MediaComment, \ + CommentSubscription, CommentNotification, Privilege, CommentReport from mediagoblin.tools import testing from mediagoblin.init.config import read_mediagoblin_config from mediagoblin.db.base import Session from mediagoblin.meddleware import BaseMeddleware -from mediagoblin.auth.lib import bcrypt_gen_password_hash +from mediagoblin.auth import gen_password_hash from mediagoblin.gmg_commands.dbupdate import run_dbupdate -from mediagoblin.init.celery import setup_celery_app + +from datetime import datetime MEDIAGOBLIN_TEST_DB_NAME = u'__mediagoblin_tests__' @@ -41,22 +41,10 @@ TEST_SERVER_CONFIG = pkg_resources.resource_filename( 'mediagoblin.tests', 'test_paste.ini') TEST_APP_CONFIG = pkg_resources.resource_filename( 'mediagoblin.tests', 'test_mgoblin_app.ini') -TEST_USER_DEV = pkg_resources.resource_filename( - 'mediagoblin.tests', 'test_user_dev') USER_DEV_DIRECTORIES_TO_SETUP = ['media/public', 'media/queue'] -BAD_CELERY_MESSAGE = """\ -Sorry, you *absolutely* must run tests with the -mediagoblin.init.celery.from_tests module. Like so: - -$ CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_tests {0} -""".format(sys.argv[0]) - - -class BadCeleryEnviron(Exception): pass - class TestingMeddleware(BaseMeddleware): """ @@ -97,12 +85,6 @@ class TestingMeddleware(BaseMeddleware): return -def suicide_if_bad_celery_environ(): - if not os.environ.get('CELERY_CONFIG_MODULE') == \ - 'mediagoblin.init.celery.from_tests': - raise BadCeleryEnviron(BAD_CELERY_MESSAGE) - - def get_app(request, paste_config=None, mgoblin_config=None): """Create a MediaGoblin app for testing. @@ -120,21 +102,13 @@ def get_app(request, paste_config=None, mgoblin_config=None): # This is the directory we're copying the paste/mgoblin config stuff into run_dir = request.config._tmpdirhandler.mktemp( 'mgoblin_app', numbered=True) - user_dev_dir = run_dir.mkdir('test_user_dev').strpath + user_dev_dir = run_dir.mkdir('user_dev').strpath new_paste_config = run_dir.join('paste.ini').strpath new_mgoblin_config = run_dir.join('mediagoblin.ini').strpath shutil.copyfile(paste_config, new_paste_config) shutil.copyfile(mgoblin_config, new_mgoblin_config) - suicide_if_bad_celery_environ() - - # Make sure we've turned on testing - testing._activate_testing() - - # Leave this imported as it sets up celery. - from mediagoblin.init.celery import from_tests - Session.rollback() Session.remove() @@ -154,9 +128,6 @@ def get_app(request, paste_config=None, mgoblin_config=None): test_app = loadapp( 'config:' + new_paste_config) - # Re-setup celery - setup_celery_app(app_config, global_config) - # Insert the TestingMeddleware, which can do some # sanity checks on every request/response. # Doing it this way is probably not the cleanest way. @@ -164,7 +135,6 @@ def get_app(request, paste_config=None, mgoblin_config=None): mg_globals.app.meddleware.insert(0, TestingMeddleware(mg_globals.app)) app = TestApp(test_app) - return app @@ -195,13 +165,13 @@ def assert_db_meets_expected(db, expected): for collection_name, collection_data in expected.iteritems(): collection = db[collection_name] for expected_document in collection_data: - document = collection.find_one({'id': expected_document['id']}) + document = collection.query.filter_by(id=expected_document['id']).first() 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=u'toast', - active_user=True): + privileges=[], wants_comment_notification=True): # Reuse existing user or create a new one test_user = User.query.filter_by(username=username).first() if test_user is None: @@ -209,13 +179,14 @@ def fixture_add_user(username=u'chris', password=u'toast', 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.pw_hash = gen_password_hash(password) + test_user.wants_comment_notification = wants_comment_notification + for privilege in privileges: + query = Privilege.query.filter(Privilege.privilege_name==privilege) + if query.count(): + test_user.all_privileges.append(query.one()) test_user.save() - # Reload test_user = User.query.filter_by(username=username).first() @@ -225,19 +196,79 @@ def fixture_add_user(username=u'chris', password=u'toast', return test_user +def fixture_comment_subscription(entry, notify=True, send_email=None): + if send_email is None: + uploader = User.query.filter_by(id=entry.uploader).first() + send_email = uploader.wants_comment_notification + + cs = CommentSubscription( + media_entry_id=entry.id, + user_id=entry.uploader, + notify=notify, + send_email=send_email) + + cs.save() + + cs = CommentSubscription.query.filter_by(id=cs.id).first() + + Session.expunge(cs) + + return cs + + +def fixture_add_comment_notification(entry_id, subject_id, user_id, + seen=False): + cn = CommentNotification(user_id=user_id, + seen=seen, + subject_id=subject_id) + cn.save() + + cn = CommentNotification.query.filter_by(id=cn.id).first() + + Session.expunge(cn) + + return cn + + def fixture_media_entry(title=u"Some title", slug=None, - uploader=None, save=True, gen_slug=True): + uploader=None, save=True, gen_slug=True, + state=u'unprocessed', fake_upload=True, + expunge=True): + """ + Add a media entry for testing purposes. + + Caution: if you're adding multiple entries with fake_upload=True, + make sure you save between them... otherwise you'll hit an + IntegrityError from multiple newly-added-MediaEntries adding + FileKeynames at once. :) + """ + if uploader is None: + uploader = fixture_add_user().id + entry = MediaEntry() entry.title = title entry.slug = slug - entry.uploader = uploader or fixture_add_user().id + entry.uploader = uploader entry.media_type = u'image' + entry.state = state + + if fake_upload: + entry.media_files = {'thumb': ['a', 'b', 'c.jpg'], + 'medium': ['d', 'e', 'f.png'], + 'original': ['g', 'h', 'i.png']} + entry.media_type = u'mediagoblin.media_types.image' if gen_slug: entry.generate_slug() + if save: entry.save() + if expunge: + entry = MediaEntry.query.filter_by(id=entry.id).first() + + Session.expunge(entry) + return entry @@ -260,3 +291,55 @@ def fixture_add_collection(name=u"My first Collection", user=None): Session.expunge(coll) return coll + +def fixture_add_comment(author=None, media_entry=None, comment=None): + if author is None: + author = fixture_add_user().id + + if media_entry is None: + media_entry = fixture_media_entry().id + + if comment is None: + comment = \ + 'Auto-generated test comment by user #{0} on media #{0}'.format( + author, media_entry) + + comment = MediaComment(author=author, + media_entry=media_entry, + content=comment) + + comment.save() + + Session.expunge(comment) + + return comment + +def fixture_add_comment_report(comment=None, reported_user=None, + reporter=None, created=None, report_content=None): + if comment is None: + comment = fixture_add_comment() + + if reported_user is None: + reported_user = fixture_add_user() + + if reporter is None: + reporter = fixture_add_user() + + if created is None: + created=datetime.now() + + if report_content is None: + report_content = \ + 'Auto-generated test report' + + comment_report = CommentReport(comment=comment, + reported_user = reported_user, + reporter = reporter, + created = created, + report_content=report_content) + + comment_report.save() + + Session.expunge(comment_report) + + return comment_report diff --git a/mediagoblin/tools/crypto.py b/mediagoblin/tools/crypto.py index 1379d21b..917e674c 100644 --- a/mediagoblin/tools/crypto.py +++ b/mediagoblin/tools/crypto.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import base64 +import string import errno import itsdangerous import logging @@ -24,6 +26,9 @@ from mediagoblin import mg_globals _log = logging.getLogger(__name__) +# produces base64 alphabet +alphabet = string.ascii_letters + "-_" +base = len(alphabet) # Use the system (hardware-based) random number generator if it exists. # -- this optimization is lifted from Django @@ -111,3 +116,13 @@ def get_timed_signer_url(namespace): assert __itsda_secret is not None return itsdangerous.URLSafeTimedSerializer(__itsda_secret, salt=namespace) + +def random_string(length): + """ Returns a URL safe base64 encoded crypographically strong string """ + rstring = "" + for i in range(length): + n = getrandbits(6) # 6 bytes = 2^6 = 64 + n = divmod(n, base)[1] + rstring += alphabet[n] + + return rstring diff --git a/mediagoblin/tools/exif.py b/mediagoblin/tools/exif.py index d0f9d0a6..6b3639e8 100644 --- a/mediagoblin/tools/exif.py +++ b/mediagoblin/tools/exif.py @@ -134,7 +134,7 @@ def _ratio_to_list(ratio): def get_useful(tags): - return dict((key, tag) for (key, tag) in tags.iteritems() if key in USEFUL_TAGS) + return dict((key, tag) for (key, tag) in tags.iteritems()) def get_gps_data(tags): diff --git a/mediagoblin/tools/mail.py b/mediagoblin/tools/mail.py index 4fa02ce5..0fabc5a9 100644 --- a/mediagoblin/tools/mail.py +++ b/mediagoblin/tools/mail.py @@ -16,7 +16,7 @@ import smtplib from email.MIMEText import MIMEText -from mediagoblin import mg_globals +from mediagoblin import mg_globals, messages from mediagoblin.tools import common ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -90,7 +90,12 @@ def send_email(from_addr, to_addrs, subject, message_body): if common.TESTS_ENABLED or mg_globals.app_config['email_debug_mode']: mhost = FakeMhost() elif not mg_globals.app_config['email_debug_mode']: - mhost = smtplib.SMTP( + if mg_globals.app_config['email_smtp_use_ssl']: + smtp_init = smtplib.SMTP_SSL + else: + smtp_init = smtplib.SMTP + + mhost = smtp_init( mg_globals.app_config['email_smtp_host'], mg_globals.app_config['email_smtp_port']) @@ -135,3 +140,16 @@ def normalize_email(email): return None email = "@".join((em_user, em_dom.lower())) return email + + +def email_debug_message(request): + """ + If the server is running in email debug mode (which is + the current default), give a debug message to the user + so that they have an idea where to find their email. + """ + if mg_globals.app_config['email_debug_mode']: + # DEBUG message, no need to translate + messages.add_message(request, messages.DEBUG, + u"This instance is running in email debug mode. " + u"The email will be on the console of the server process.") diff --git a/mediagoblin/tools/pagination.py b/mediagoblin/tools/pagination.py index d0f08c94..855878e0 100644 --- a/mediagoblin/tools/pagination.py +++ b/mediagoblin/tools/pagination.py @@ -18,7 +18,7 @@ import urllib import copy from math import ceil, floor from itertools import izip, count - +from werkzeug.datastructures import MultiDict PAGINATION_DEFAULT_PER_PAGE = 30 @@ -98,7 +98,11 @@ class Pagination(object): """ Get a page url by adding a page= parameter to the base url """ - new_get_params = dict(get_params) or {} + if isinstance(get_params, MultiDict): + new_get_params = get_params.to_dict() + else: + new_get_params = dict(get_params) or {} + new_get_params['page'] = page_no return "%s?%s" % ( base_url, urllib.urlencode(new_get_params)) diff --git a/mediagoblin/tools/pluginapi.py b/mediagoblin/tools/pluginapi.py index 3f98aa8a..1eabe9f1 100644 --- a/mediagoblin/tools/pluginapi.py +++ b/mediagoblin/tools/pluginapi.py @@ -252,7 +252,7 @@ def get_hook_templates(hook_name): .. code-block:: html+jinja - {% template_hook "media_sidebar" %} + {% template_hook("media_sidebar") %} ... which will include all templates for you, partly using this method. diff --git a/mediagoblin/tools/request.py b/mediagoblin/tools/request.py index ee342eae..d4739039 100644 --- a/mediagoblin/tools/request.py +++ b/mediagoblin/tools/request.py @@ -14,12 +14,18 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import json import logging from mediagoblin.db.models import User _log = logging.getLogger(__name__) +# MIME-Types +form_encoded = "application/x-www-form-urlencoded" +json_encoded = "application/json" + + def setup_user_in_request(request): """ Examine a request and tack on a request.user parameter if that's @@ -36,3 +42,15 @@ def setup_user_in_request(request): # this session. _log.warn("Killing session for user id %r", request.session['user_id']) request.session.delete() + +def decode_request(request): + """ Decodes a request based on MIME-Type """ + data = request.get_data() + + if request.content_type == json_encoded: + data = json.loads(data) + elif request.content_type == form_encoded or request.content_type == "": + data = request.form + else: + data = "" + return data diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py index 80df1f5a..cd99a230 100644 --- a/mediagoblin/tools/response.py +++ b/mediagoblin/tools/response.py @@ -14,11 +14,15 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import json + import werkzeug.utils from werkzeug.wrappers import Response as wz_Response from mediagoblin.tools.template import render_template from mediagoblin.tools.translate import (lazy_pass_to_ugettext as _, pass_to_ugettext) +from mediagoblin.db.models import UserBan, User +from datetime import date class Response(wz_Response): """Set default response mimetype to HTML, otherwise we get text/plain""" @@ -31,7 +35,6 @@ def render_to_response(request, template, context, status=200): render_template(request, template, context), status=status) - def render_error(request, status=500, title=_('Oops!'), err_msg=_('An error occured')): """Render any error page with a given error code, title and text body @@ -44,6 +47,15 @@ def render_error(request, status=500, title=_('Oops!'), {'err_code': status, 'title': title, 'err_msg': err_msg}), status=status) +def render_400(request, err_msg=None): + """ Render a standard 400 page""" + _ = pass_to_ugettext + title = _("Bad Request") + if err_msg is None: + err_msg = _("The request sent to the server is invalid, \ +please double check it") + + return render_error(request, 400, title, err_msg) def render_403(request): """Render a standard 403 page""" @@ -62,6 +74,21 @@ def render_404(request): "you're looking for has been moved or deleted.") return render_error(request, 404, err_msg=err_msg) +def render_user_banned(request): + """Renders the page which tells a user they have been banned, for how long + and the reason why they have been banned" + """ + user_ban = UserBan.query.get(request.user.id) + if (user_ban.expiration_date is not None and + date.today()>user_ban.expiration_date): + + user_ban.delete() + return redirect(request, + 'index') + return render_to_response(request, + 'mediagoblin/banned.html', + {'reason':user_ban.reason, + 'expiration_date':user_ban.expiration_date}) def render_http_exception(request, exc, description): """Return Response() given a werkzeug.HTTPException @@ -77,7 +104,7 @@ def render_http_exception(request, exc, description): elif stock_desc and exc.code == 404: return render_404(request) - return render_error(request, title=exc.args[0], + return render_error(request, title='{0} {1}'.format(exc.code, exc.name), err_msg=description, status=exc.code) @@ -99,3 +126,52 @@ def redirect(request, *args, **kwargs): if querystring: location += querystring return werkzeug.utils.redirect(location) + + +def redirect_obj(request, obj): + """Redirect to the page for the given object. + + Requires obj to have a .url_for_self method.""" + return redirect(request, location=obj.url_for_self(request.urlgen)) + +def json_response(serializable, _disable_cors=False, *args, **kw): + ''' + Serializes a json objects and returns a werkzeug Response object with the + serialized value as the response body and Content-Type: application/json. + + :param serializable: A json-serializable object + + Any extra arguments and keyword arguments are passed to the + Response.__init__ method. + ''' + + response = wz_Response(json.dumps(serializable), *args, content_type='application/json', **kw) + + if not _disable_cors: + cors_headers = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'} + for key, value in cors_headers.iteritems(): + response.headers.set(key, value) + + return response + +def form_response(data, *args, **kwargs): + """ + Responds using application/x-www-form-urlencoded and returns a werkzeug + Response object with the data argument as the body + and 'application/x-www-form-urlencoded' as the Content-Type. + + Any extra arguments and keyword arguments are passed to the + Response.__init__ method. + """ + + response = wz_Response( + data, + content_type="application/x-www-form-urlencoded", + *args, + **kwargs + ) + + return response diff --git a/mediagoblin/tools/session.py b/mediagoblin/tools/session.py index fdc32523..a57f69cc 100644 --- a/mediagoblin/tools/session.py +++ b/mediagoblin/tools/session.py @@ -17,10 +17,12 @@ import itsdangerous import logging -import crypto +from mediagoblin.tools import crypto _log = logging.getLogger(__name__) +MAX_AGE = 30 * 24 * 60 * 60 + class Session(dict): def __init__(self, *args, **kwargs): self.send_new_cookie = False @@ -64,5 +66,10 @@ class SessionManager(object): elif not session: response.delete_cookie(self.cookie_name) else: + if session.get('stay_logged_in', False): + max_age = MAX_AGE + else: + max_age = None + response.set_cookie(self.cookie_name, self.signer.dumps(session), - httponly=True) + max_age=max_age, httponly=True) diff --git a/mediagoblin/tools/staticdirect.py b/mediagoblin/tools/staticdirect.py index 31abc566..8381b8b6 100644 --- a/mediagoblin/tools/staticdirect.py +++ b/mediagoblin/tools/staticdirect.py @@ -35,7 +35,8 @@ class StaticDirect(object): staticdirect to. In general, you should supply a None domain, as that's the "default" domain. - Things work like this: + Things work like this:: + >>> staticdirect = StaticDirect( ... {None: "/static/", ... "theme": "http://example.org/themestatic/"}) @@ -61,3 +62,42 @@ class StaticDirect(object): def get(self, filepath, domain=None): return '%s/%s' % ( self.domains[domain], filepath.lstrip('/')) + + +class PluginStatic(object): + """Pass this into the ``'static_setup'`` hook to register your + plugin's static directory. + + This has two mandatory attributes that you must pass in on class + init: + + - *name:* this name will be both used for lookup in "urlgen" for + your plugin's static resources and for the subdirectory that + it'll be "mounted" to for serving via your web browser. It + *MUST* be unique. If writing a plugin bundled with MediaGoblin + please use the pattern 'coreplugin__foo' where 'foo' is your + plugin name. All external plugins should use their modulename, + so if your plugin is 'mg_bettertags' you should also call this + name 'mg_bettertags'. + - *file_path:* the directory your plugin's static resources are + located in. It's recommended that you use + pkg_resources.resource_filename() for this. + + An example of using this:: + + from pkg_resources import resource_filename + from mediagoblin.tools.staticdirect import PluginStatic + + hooks = { + 'static_setup': lambda: PluginStatic( + 'mg_bettertags', + resource_filename('mg_bettertags', 'static')) + } + + """ + def __init__(self, name, file_path): + self.name = name + self.file_path = file_path + + def __call__(self): + return self diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py index 5d320f75..e5acdf45 100644 --- a/mediagoblin/tools/template.py +++ b/mediagoblin/tools/template.py @@ -29,12 +29,11 @@ from mediagoblin.tools import common from mediagoblin.tools.translate import is_rtl from mediagoblin.tools.translate import set_thread_locale from mediagoblin.tools.translate import get_locale_from_request -from mediagoblin.tools.pluginapi import get_hook_templates +from mediagoblin.tools.pluginapi import get_hook_templates, hook_transform from mediagoblin.tools.timesince import timesince from mediagoblin.meddleware.csrf import render_csrf_form_token - SETUP_JINJA_ENVS = {} @@ -52,6 +51,12 @@ def get_jinja_env(template_loader, locale): if locale in SETUP_JINJA_ENVS: return SETUP_JINJA_ENVS[locale] + # The default config does not require a [jinja2] block. + # You may create one if you wish to enable additional jinja2 extensions, + # see example in config_spec.ini + jinja2_config = mg_globals.global_config.get('jinja2', {}) + local_exts = jinja2_config.get('extensions', []) + # jinja2.StrictUndefined will give exceptions on references # to undefined/unknown variables in templates. template_env = jinja2.Environment( @@ -59,7 +64,7 @@ def get_jinja_env(template_loader, locale): undefined=jinja2.StrictUndefined, extensions=[ 'jinja2.ext.i18n', 'jinja2.ext.autoescape', - TemplateHookExtension]) + TemplateHookExtension] + local_exts) template_env.install_gettext_callables( mg_globals.thread_scope.translations.ugettext, @@ -74,6 +79,7 @@ def get_jinja_env(template_loader, locale): template_env.globals['app_config'] = mg_globals.app_config template_env.globals['global_config'] = mg_globals.global_config template_env.globals['version'] = _version.__version__ + template_env.globals['auth'] = mg_globals.app.auth template_env.globals['is_rtl'] = is_rtl(locale) template_env.filters['urlencode'] = url_quote_plus @@ -83,6 +89,19 @@ def get_jinja_env(template_loader, locale): # allow for hooking up plugin templates template_env.globals['get_hook_templates'] = get_hook_templates + template_env.globals = hook_transform( + 'template_global_context', template_env.globals) + + #### THIS IS TEMPORARY, PLEASE FIX IT + ## Notifications stuff is not yet a plugin (and we're not sure it will be), + ## but it needs to add stuff to the context. This is THE WRONG WAY TO DO IT + from mediagoblin import notifications + template_env.globals['get_notifications'] = notifications.get_notifications + template_env.globals[ + 'get_notification_count'] = notifications.get_notification_count + template_env.globals[ + 'get_comment_subscription'] = notifications.get_comment_subscription + if exists(locale): SETUP_JINJA_ENVS[locale] = template_env @@ -106,6 +125,20 @@ def render_template(request, template_path, context): rendered_csrf_token = render_csrf_form_token(request) if rendered_csrf_token is not None: context['csrf_token'] = render_csrf_form_token(request) + + # allow plugins to do things to the context + if request.controller_name: + context = hook_transform( + (request.controller_name, template_path), + context) + + # More evil: allow plugins to possibly do something to the context + # in every request ever with access to the request and other + # variables. Note: this is slower than using + # template_global_context + context = hook_transform( + 'template_context_prerender', context) + rendered = template.render(context) if common.TESTS_ENABLED: diff --git a/mediagoblin/tools/validator.py b/mediagoblin/tools/validator.py new file mode 100644 index 00000000..03598f9c --- /dev/null +++ b/mediagoblin/tools/validator.py @@ -0,0 +1,46 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 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 wtforms.validators import Email, URL + +def validate_email(email): + """ + Validates an email + + Returns True if valid and False if invalid + """ + + email_re = Email().regex + result = email_re.match(email) + if result is None: + return False + else: + return result.string + +def validate_url(url): + """ + Validates a url + + Returns True if valid and False if invalid + """ + + url_re = URL().regex + result = url_re.match(url) + if result is None: + return False + else: + return result.string + diff --git a/mediagoblin/user_pages/forms.py b/mediagoblin/user_pages/forms.py index 9a193680..eb786f47 100644 --- a/mediagoblin/user_pages/forms.py +++ b/mediagoblin/user_pages/forms.py @@ -23,7 +23,7 @@ class MediaCommentForm(wtforms.Form): _('Comment'), [wtforms.validators.Required()], description=_(u'You can use ' - u'<a href="http://daringfireball.net/projects/markdown/basics">' + u'<a href="http://daringfireball.net/projects/markdown/basics" target="_blank">' u'Markdown</a> for formatting.')) class ConfirmDeleteForm(wtforms.Form): @@ -47,5 +47,17 @@ class MediaCollectForm(wtforms.Form): collection_description = wtforms.TextAreaField( _('Description of this collection'), description=_("""You can use - <a href="http://daringfireball.net/projects/markdown/basics"> + <a href="http://daringfireball.net/projects/markdown/basics" target="_blank"> Markdown</a> for formatting.""")) + +class CommentReportForm(wtforms.Form): + report_reason = wtforms.TextAreaField( + _('Reason for Reporting'), + [wtforms.validators.Required()]) + reporter_id = wtforms.HiddenField('') + +class MediaReportForm(wtforms.Form): + report_reason = wtforms.TextAreaField( + _('Reason for Reporting'), + [wtforms.validators.Required()]) + reporter_id = wtforms.HiddenField('') diff --git a/mediagoblin/user_pages/lib.py b/mediagoblin/user_pages/lib.py index 2f47e4b1..e5c8defc 100644 --- a/mediagoblin/user_pages/lib.py +++ b/mediagoblin/user_pages/lib.py @@ -19,7 +19,9 @@ from mediagoblin.tools.template import render_template from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin import mg_globals from mediagoblin.db.base import Session -from mediagoblin.db.models import CollectionItem +from mediagoblin.db.models import (CollectionItem, MediaReport, CommentReport, + MediaComment, MediaEntry) +from mediagoblin.user_pages import forms as user_forms def send_comment_email(user, comment, media, request): @@ -69,9 +71,48 @@ def add_media_to_collection(collection, media, note=None, commit=True): collection.items = collection.items + 1 Session.add(collection) - - media.collected = media.collected + 1 Session.add(media) if commit: Session.commit() + +def build_report_object(report_form, media_entry=None, comment=None): + """ + This function is used to convert a form object (from a User filing a + report) into either a MediaReport or CommentReport object. + + :param report_form A MediaReportForm or a CommentReportForm object + with valid information from a POST request. + :param media_entry A MediaEntry object. The MediaEntry being repo- + -rted by a MediaReport. In a CommentReport, + this will be None. + :param comment A MediaComment object. The MediaComment being + reported by a CommentReport. In a MediaReport + this will be None. + + :returns A MediaReport object if a valid MediaReportForm is + passed as kwarg media_entry. This MediaReport has + not been saved. + :returns A CommentReport object if a valid CommentReportForm + is passed as kwarg comment. This CommentReport + has not been saved. + :returns None if the form_dict is invalid. + """ + + if report_form.validate() and comment is not None: + report_object = CommentReport() + report_object.comment_id = comment.id + report_object.reported_user_id = MediaComment.query.get( + comment.id).get_author.id + elif report_form.validate() and media_entry is not None: + report_object = MediaReport() + report_object.media_entry_id = media_entry.id + report_object.reported_user_id = MediaEntry.query.get( + media_entry.id).get_uploader.id + else: + return None + + report_object.report_content = report_form.report_reason.data + report_object.reporter_id = report_form.reporter_id.data + return report_object + diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py index 9cb665b5..f0f4d8b7 100644 --- a/mediagoblin/user_pages/routing.py +++ b/mediagoblin/user_pages/routing.py @@ -23,6 +23,10 @@ add_route('mediagoblin.user_pages.media_home', '/u/<string:user>/m/<string:media>/', 'mediagoblin.user_pages.views:media_home') +add_route('mediagoblin.user_pages.media_home.report_media', + '/u/<string:user>/m/<string:media>/report/', + 'mediagoblin.user_pages.views:file_a_report') + add_route('mediagoblin.user_pages.media_confirm_delete', '/u/<string:user>/m/<int:media_id>/confirm-delete/', 'mediagoblin.user_pages.views:media_confirm_delete') @@ -32,6 +36,10 @@ add_route('mediagoblin.user_pages.media_post_comment', '/u/<string:user>/m/<int:media_id>/comment/add/', 'mediagoblin.user_pages.views:media_post_comment') +add_route('mediagoblin.user_pages.media_preview_comment', + '/ajax/comment/preview/', + 'mediagoblin.user_pages.views:media_preview_comment') + add_route('mediagoblin.user_pages.user_gallery', '/u/<string:user>/gallery/', 'mediagoblin.user_pages.views:user_gallery') @@ -40,6 +48,10 @@ add_route('mediagoblin.user_pages.media_home.view_comment', '/u/<string:user>/m/<string:media>/c/<int:comment>/', 'mediagoblin.user_pages.views:media_home') +add_route('mediagoblin.user_pages.media_home.report_comment', + '/u/<string:user>/m/<string:media>/c/<int:comment>/report/', + 'mediagoblin.user_pages.views:file_a_report') + # User's tags gallery add_route('mediagoblin.user_pages.user_tag_gallery', '/u/<string:user>/tag/<string:tag>/', diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index 21b0c016..64fa793e 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -16,42 +16,47 @@ import logging import datetime +import json from mediagoblin import messages, mg_globals from mediagoblin.db.models import (MediaEntry, MediaTag, Collection, CollectionItem, User) -from mediagoblin.tools.response import render_to_response, render_404, redirect +from mediagoblin.tools.response import render_to_response, render_404, \ + redirect, redirect_obj +from mediagoblin.tools.text import cleaned_markdown_conversion from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools.pagination import Pagination from mediagoblin.user_pages import forms as user_forms from mediagoblin.user_pages.lib import (send_comment_email, - add_media_to_collection) + add_media_to_collection, build_report_object) +from mediagoblin.notifications import trigger_notification, \ + add_comment_subscription, mark_comment_notification_seen from mediagoblin.decorators import (uses_pagination, get_user_media_entry, - get_media_entry_by_id, + get_media_entry_by_id, user_has_privilege, user_not_banned, require_active_login, user_may_delete_media, user_may_alter_collection, - get_user_collection, get_user_collection_item, active_user_from_url) + get_user_collection, get_user_collection_item, active_user_from_url, + get_optional_media_comment_by_id, allow_reporting) from werkzeug.contrib.atom import AtomFeed +from werkzeug.exceptions import MethodNotAllowed +from werkzeug.wrappers import Response _log = logging.getLogger(__name__) _log.setLevel(logging.DEBUG) - +@user_not_banned @uses_pagination def user_home(request, page): """'Homepage' of a User()""" - # TODO: decide if we only want homepages for active users, we can - # then use the @get_active_user decorator and also simplify the - # template html. user = User.query.filter_by(username=request.matchdict['user']).first() if not user: return render_404(request) - elif user.status != u'active': + elif not user.has_privilege(u'active'): return render_to_response( request, - 'mediagoblin/user_pages/user.html', + 'mediagoblin/user_pages/user_nonactive.html', {'user': user}) cursor = MediaEntry.query.\ @@ -77,7 +82,7 @@ def user_home(request, page): 'media_entries': media_entries, 'pagination': pagination}) - +@user_not_banned @active_user_from_url @uses_pagination def user_gallery(request, page, url_user=None): @@ -109,9 +114,10 @@ def user_gallery(request, page, url_user=None): 'media_entries': media_entries, 'pagination': pagination}) -MEDIA_COMMENTS_PER_PAGE = 50 +MEDIA_COMMENTS_PER_PAGE = 50 +@user_not_banned @get_user_media_entry @uses_pagination def media_home(request, media, page, **kwargs): @@ -120,6 +126,9 @@ def media_home(request, media, page, **kwargs): """ comment_id = request.matchdict.get('comment', None) if comment_id: + if request.user: + mark_comment_notification_seen(comment_id, request.user) + pagination = Pagination( page, media.get_comments( mg_globals.app_config['comments_ascending']), @@ -135,7 +144,7 @@ def media_home(request, media, page, **kwargs): comment_form = user_forms.MediaCommentForm(request.form) - media_template_name = media.media_manager['display_template'] + media_template_name = media.media_manager.display_template return render_to_response( request, @@ -148,19 +157,26 @@ def media_home(request, media, page, **kwargs): @get_media_entry_by_id -@require_active_login +@user_has_privilege(u'commenter') def media_post_comment(request, media): """ recieves POST from a MediaEntry() comment form, saves the comment. """ - assert request.method == 'POST' + if not request.method == 'POST': + raise MethodNotAllowed() comment = request.db.MediaComment() comment.media_entry = media.id comment.author = request.user.id comment.content = unicode(request.form['comment_content']) - if not comment.content.strip(): + # Show error message if commenting is disabled. + if not mg_globals.app_config['allow_comments']: + messages.add_message( + request, + messages.ERROR, + _("Sorry, comments are disabled.")) + elif not comment.content.strip(): messages.add_message( request, messages.ERROR, @@ -172,15 +188,26 @@ def media_post_comment(request, media): request, messages.SUCCESS, _('Your comment has been posted!')) - media_uploader = media.get_uploader - #don't send email if you comment on your own post - if (comment.author != media_uploader and - media_uploader.wants_comment_notification): - send_comment_email(media_uploader, comment, media, request) + trigger_notification(comment, media, request) + + add_comment_subscription(request.user, media) - return redirect(request, location=media.url_for_self(request.urlgen)) + return redirect_obj(request, media) + +def media_preview_comment(request): + """Runs a comment through markdown so it can be previewed.""" + # If this isn't an ajax request, render_404 + if not request.is_xhr: + return render_404(request) + + comment = unicode(request.form['comment_content']) + cleancomment = { "content":cleaned_markdown_conversion(comment)} + + return Response(json.dumps(cleancomment)) + +@user_not_banned @get_media_entry_by_id @require_active_login def media_collect(request, media): @@ -255,9 +282,7 @@ def media_collect(request, media): _('"%s" added to collection "%s"') % (media.title, collection.title)) - return redirect(request, "mediagoblin.user_pages.media_home", - user=media.get_uploader.username, - media=media.slug_or_id) + return redirect_obj(request, media) #TODO: Why does @user_may_delete_media not implicate @require_active_login? @@ -271,21 +296,30 @@ def media_confirm_delete(request, media): if request.method == 'POST' and form.validate(): if form.confirm.data is True: username = media.get_uploader.username + + media.get_uploader.uploaded = media.get_uploader.uploaded - \ + media.file_size + media.get_uploader.save() + # Delete MediaEntry and all related files, comments etc. media.delete() messages.add_message( request, messages.SUCCESS, _('You deleted the media.')) - return redirect(request, "mediagoblin.user_pages.user_home", - user=username) + location = media.url_to_next(request.urlgen) + if not location: + location=media.url_to_prev(request.urlgen) + if not location: + location=request.urlgen("mediagoblin.user_pages.user_home", + user=username) + return redirect(request, location=location) else: messages.add_message( request, messages.ERROR, _("The media was not deleted because you didn't check that you were sure.")) - return redirect(request, - location=media.url_for_self(request.urlgen)) + return redirect_obj(request, media) - if ((request.user.is_admin and + if ((request.user.has_privilege(u'admin') and request.user.id != media.uploader)): messages.add_message( request, messages.WARNING, @@ -298,7 +332,7 @@ def media_confirm_delete(request, media): {'media': media, 'form': form}) - +@user_not_banned @active_user_from_url @uses_pagination def user_collection(request, page, url_user=None): @@ -328,7 +362,7 @@ def user_collection(request, page, url_user=None): 'collection_items': collection_items, 'pagination': pagination}) - +@user_not_banned @active_user_from_url def collection_list(request, url_user=None): """A User-defined Collection""" @@ -355,7 +389,6 @@ def collection_item_confirm_remove(request, collection_item): if form.confirm.data is True: entry = collection_item.get_media_entry - entry.collected = entry.collected - 1 entry.save() collection_item.delete() @@ -369,11 +402,9 @@ def collection_item_confirm_remove(request, collection_item): request, messages.ERROR, _("The item was not removed because you didn't check that you were sure.")) - return redirect(request, "mediagoblin.user_pages.user_collection", - user=username, - collection=collection.slug) + return redirect_obj(request, collection) - if ((request.user.is_admin and + if ((request.user.has_privilege(u'admin') and request.user.id != collection_item.in_collection.creator)): messages.add_message( request, messages.WARNING, @@ -404,7 +435,6 @@ def collection_confirm_delete(request, collection): # Delete all the associated collection items for item in collection.get_collection_items(): entry = item.get_media_entry - entry.collected = entry.collected - 1 entry.save() item.delete() @@ -419,11 +449,9 @@ def collection_confirm_delete(request, collection): request, messages.ERROR, _("The collection was not deleted because you didn't check that you were sure.")) - return redirect(request, "mediagoblin.user_pages.user_collection", - user=username, - collection=collection.slug) + return redirect_obj(request, collection) - if ((request.user.is_admin and + if ((request.user.has_privilege(u'admin') and request.user.id != collection.creator)): messages.add_message( request, messages.WARNING, @@ -445,9 +473,8 @@ def atom_feed(request): generates the atom feed with the newest images """ user = User.query.filter_by( - username = request.matchdict['user'], - status = u'active').first() - if not user: + username = request.matchdict['user']).first() + if not user or not user.has_privilege(u'active'): return render_404(request) cursor = MediaEntry.query.filter_by( @@ -508,9 +535,8 @@ def collection_atom_feed(request): generates the atom feed with the newest images from a collection """ user = User.query.filter_by( - username = request.matchdict['user'], - status = u'active').first() - if not user: + username = request.matchdict['user']).first() + if not user or not user.has_privilege(u'active'): return render_404(request) collection = Collection.query.filter_by( @@ -528,9 +554,7 @@ def collection_atom_feed(request): ATOM feed id is a tag URI (see http://en.wikipedia.org/wiki/Tag_URI) """ atomlinks = [{ - 'href': request.urlgen( - 'mediagoblin.user_pages.user_collection', - qualified=True, user=request.matchdict['user'], collection=collection.slug), + 'href': collection.url_for_self(request.urlgen, qualified=True), 'rel': 'alternate', 'type': 'text/html' }] @@ -574,7 +598,6 @@ def collection_atom_feed(request): return feed.get_response() - @require_active_login def processing_panel(request): """ @@ -586,7 +609,7 @@ def processing_panel(request): # # Make sure we have permission to access this user's panel. Only # admins and this user herself should be able to do so. - if not (user.id == request.user.id or request.user.is_admin): + if not (user.id == request.user.id or request.user.has_privilege(u'admin')): # No? Simply redirect to this user's homepage. return redirect( request, 'mediagoblin.user_pages.user_home', @@ -618,3 +641,44 @@ def processing_panel(request): 'processing_entries': processing_entries, 'failed_entries': failed_entries, 'processed_entries': processed_entries}) + +@allow_reporting +@get_user_media_entry +@user_has_privilege(u'reporter') +@get_optional_media_comment_by_id +def file_a_report(request, media, comment): + """ + This view handles the filing of a MediaReport or a CommentReport. + """ + if comment is not None: + if not comment.get_media_entry.id == media.id: + return render_404(request) + + form = user_forms.CommentReportForm(request.form) + context = {'media': media, + 'comment':comment, + 'form':form} + else: + form = user_forms.MediaReportForm(request.form) + context = {'media': media, + 'form':form} + form.reporter_id.data = request.user.id + + + if request.method == "POST": + report_object = build_report_object(form, + media_entry=media, + comment=comment) + + # if the object was built successfully, report_table will not be None + if report_object: + report_object.save() + return redirect( + request, + 'index') + + + return render_to_response( + request, + 'mediagoblin/user_pages/report.html', + context) diff --git a/mediagoblin/views.py b/mediagoblin/views.py index 6acd7e96..4185c1b6 100644 --- a/mediagoblin/views.py +++ b/mediagoblin/views.py @@ -17,11 +17,11 @@ from mediagoblin import mg_globals from mediagoblin.db.models import MediaEntry from mediagoblin.tools.pagination import Pagination -from mediagoblin.tools.response import render_to_response -from mediagoblin.decorators import uses_pagination - +from mediagoblin.tools.response import render_to_response, render_404 +from mediagoblin.decorators import uses_pagination, user_not_banned +@user_not_banned @uses_pagination def root_view(request, page): cursor = MediaEntry.query.filter_by(state=u'processed').\ @@ -44,3 +44,10 @@ def simple_template_render(request): template_name = request.matchdict['template'] return render_to_response( request, template_name, {}) + +def terms_of_service(request): + if mg_globals.app_config["show_tos"] is False: + return render_404(request) + + return render_to_response(request, + 'mediagoblin/terms_of_service.html', {}) @@ -14,6 +14,7 @@ use = egg:Paste#urlmap /mgoblin_media/ = publicstore_serve /mgoblin_static/ = mediagoblin_static /theme_static/ = theme_static +/plugin_static/ = plugin_static [app:mediagoblin] use = egg:mediagoblin#app @@ -56,6 +57,11 @@ use = egg:Paste#static document_root = %(here)s/user_dev/theme_static/ cache_max_age = 86400 +[app:plugin_static] +use = egg:Paste#static +document_root = %(here)s/user_dev/plugin_static/ +cache_max_age = 86400 + [filter:errors] use = egg:mediagoblin#errors debug = false diff --git a/runtests.sh b/runtests.sh index 382e2fa6..00164a78 100755 --- a/runtests.sh +++ b/runtests.sh @@ -39,10 +39,6 @@ else fi -CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_tests -export CELERY_CONFIG_MODULE -echo "+ CELERY_CONFIG_MODULE=$CELERY_CONFIG_MODULE" - # Look to see if the user has specified a specific directory/file to # run tests out of. If not we'll need to pass along # mediagoblin/tests/ later very specifically. Otherwise py.test @@ -32,8 +32,8 @@ def get_version(): raise RuntimeError("Unable to find version string in %s." % VERSIONFILE) - -setup( +try: + setup( name="mediagoblin", version=get_version(), packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), @@ -42,27 +42,29 @@ setup( # scripts and dependencies install_requires=[ 'setuptools', + 'python-dateutil', 'PasteScript', 'wtforms', 'py-bcrypt', - 'pytest', + 'pytest>=2.3.1', 'pytest-xdist', 'werkzeug>=0.7', - 'celery==2.5.3', - 'kombu==2.1.7', + 'celery>=3.0', + 'kombu', 'jinja2', 'sphinx', - 'Babel', + 'Babel<1.0', 'argparse', 'webtest<2', 'ConfigObj', 'Markdown', - 'sqlalchemy>=0.7.0', + 'sqlalchemy<0.9.0', 'sqlalchemy-migrate', 'mock', 'itsdangerous', 'pytz', 'six', + 'oauthlib==0.5.0', ## This is optional! # 'translitcodec', ## For now we're expecting that users will install this from @@ -106,3 +108,17 @@ setup( "Topic :: Internet :: WWW/HTTP :: Dynamic Content" ], ) +except TypeError, e: + # Check if the problem is caused by the sqlalchemy/setuptools conflict + msg_as_str = str(e) + if not (msg_as_str == 'dist must be a Distribution instance'): + raise + + # If so, tell the user it is OK to just run the script again. + print "\n\n---------- NOTE ----------" + print "The setup.py command you ran failed." + print "" + print ("It is a known possible failure. Just run it again. It works the " + "second time.") + import sys + sys.exit(1) |