From ee355966c84fb32541b3940eee6adae15c89cc19 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 3 May 2013 08:50:30 -0700 Subject: [PATCH 001/153] basic_auth v0 plugin working --- mediagoblin.ini | 1 + mediagoblin/auth/__init__.py | 29 +++++++ mediagoblin/auth/forms.py | 26 ------ mediagoblin/auth/views.py | 39 ++------- mediagoblin/plugins/basic_auth/__init__.py | 95 ++++++++++++++++++++++ mediagoblin/plugins/basic_auth/forms.py | 30 +++++++ 6 files changed, 162 insertions(+), 58 deletions(-) create mode 100644 mediagoblin/plugins/basic_auth/__init__.py create mode 100644 mediagoblin/plugins/basic_auth/forms.py diff --git a/mediagoblin.ini b/mediagoblin.ini index 4906546a..057084ae 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -47,3 +47,4 @@ base_url = /mgoblin_media/ # documentation for details. [plugins] [[mediagoblin.plugins.geolocation]] +[[mediagoblin.plugins.basic_auth]] diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index 621845ba..2460c048 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 . +from mediagoblin.tools.pluginapi import hook_handle + + +def check_login(user, login_form): + return hook_handle("auth_check_login", user, login_form) + + +def get_user(*args): + return hook_handle("auth_get_user", *args) + + +def create_user(*args): + return hook_handle("auth_create_user", *args) + + +def extra_validation(register_form, *args): + return hook_handle("auth_extra_validation", register_form, *args) + + +def get_user_metadata(user): + return hook_handle("auth_get_user_metadata", user) + + +def get_login_form(request): + return hook_handle("auth_get_login_form", request) + + +def get_registration_form(request): + return hook_handle("auth_get_registration_form", request) diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 599b2576..bab0d35e 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -21,32 +21,6 @@ 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)]) - password = wtforms.PasswordField( - _('Password'), - [wtforms.validators.Required(), - wtforms.validators.Length(min=5, max=1024)]) - email = wtforms.TextField( - _('Email address'), - [wtforms.validators.Required(), - normalize_user_or_email_field(allow_user=False)]) - - -class LoginForm(wtforms.Form): - username = wtforms.TextField( - _('Username or Email'), - [wtforms.validators.Required(), - normalize_user_or_email_field()]) - password = wtforms.PasswordField( - _('Password'), - [wtforms.validators.Required(), - wtforms.validators.Length(min=5, max=1024)]) - - class ForgotPassForm(wtforms.Form): username = wtforms.TextField( _('Username or email'), diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dc408911..2b3b036a 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -25,6 +25,7 @@ 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 +import mediagoblin.auth as auth from sqlalchemy import or_ def email_debug_message(request): @@ -54,33 +55,15 @@ def register(request): _('Sorry, registration is disabled on this instance.')) return redirect(request, "index") - register_form = auth_forms.RegistrationForm(request.form) + register_form = 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 + extra_validation_passes = auth.extra_validation(register_form) 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() + user = auth.create_user(register_form) # log the user in request.session['user_id'] = unicode(user.id) @@ -108,23 +91,15 @@ def login(request): If you provide the POST with 'next', it'll redirect to that view. """ - login_form = auth_forms.LoginForm(request.form) + login_form = auth.get_login_form(request) login_failed = False if request.method == 'POST': - - username = login_form.data['username'] - if login_form.validate(): - user = User.query.filter( - or_( - User.username == username, - User.email == username, + user = auth.get_user(login_form) - )).first() - - if user and user.check_login(login_form.password.data): + if user and auth.check_login(user, login_form): # set up login in session request.session['user_id'] = unicode(user.id) request.session.save() diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py new file mode 100644 index 00000000..ca3d2516 --- /dev/null +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -0,0 +1,95 @@ +# 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 . +import os +import uuid + +import forms as auth_forms +from mediagoblin.auth import lib as auth_lib +from mediagoblin.db.models import User +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools import pluginapi +from sqlalchemy import or_ + + +PLUGIN_DIR = os.path.dirname(__file__) + + +def setup_plugin(): + config = pluginapi.get_config('mediagoblin.pluginapi.basic_auth') + + +def check_login(user, login_form): + return user.check_login(login_form.password.data) + + +def get_user(login_form): + username = login_form.data['username'] + user = User.query.filter( + or_( + User.username == username, + User.email == username, + )).first() + return user + + +def create_user(registration_form): + user = User() + user.username = registration_form.data['username'] + user.email = registration_form.data['email'] + user.pw_hash = auth_lib.bcrypt_gen_password_hash( + registration_form.password.data) + user.verification_key = unicode(uuid.uuid4()) + user.save() + return user + + +def extra_validation(register_form, *args): + 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 + + return extra_validation_passes + + +def get_login_form(request): + return auth_forms.LoginForm(request.form) + + +def get_registration_form(request): + return auth_forms.RegistrationForm(request.form) + + +hooks = { + 'setup': setup_plugin, + 'auth_check_login': check_login, + 'auth_get_user': get_user, + 'auth_create_user': create_user, + 'auth_extra_validation': extra_validation, + 'auth_get_login_form': get_login_form, + 'auth_get_registration_form': get_registration_form, +} diff --git a/mediagoblin/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py new file mode 100644 index 00000000..28eb7d0a --- /dev/null +++ b/mediagoblin/plugins/basic_auth/forms.py @@ -0,0 +1,30 @@ +import wtforms + +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.auth.forms 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)]) + password = wtforms.PasswordField( + _('Password'), + [wtforms.validators.Required(), + wtforms.validators.Length(min=5, max=1024)]) + email = wtforms.TextField( + _('Email address'), + [wtforms.validators.Required(), + normalize_user_or_email_field(allow_user=False)]) + + +class LoginForm(wtforms.Form): + username = wtforms.TextField( + _('Username or Email'), + [wtforms.validators.Required(), + normalize_user_or_email_field()]) + password = wtforms.PasswordField( + _('Password'), + [wtforms.validators.Required(), + wtforms.validators.Length(min=5, max=1024)]) From ebbc8fe0692e556116b4cf2c38f28152eb5ef185 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 3 May 2013 13:28:03 -0700 Subject: [PATCH 002/153] reset mediagoblin.ini --- mediagoblin.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/mediagoblin.ini b/mediagoblin.ini index 057084ae..4906546a 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -47,4 +47,3 @@ base_url = /mgoblin_media/ # documentation for details. [plugins] [[mediagoblin.plugins.geolocation]] -[[mediagoblin.plugins.basic_auth]] From 77e1aca8dbbf446f5cf24cb508f28a4fa9c04bc9 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 3 May 2013 13:48:48 -0700 Subject: [PATCH 003/153] added login.html template hook and basic_auth login template --- mediagoblin/plugins/basic_auth/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index ca3d2516..6500151a 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -24,9 +24,6 @@ from mediagoblin.tools import pluginapi from sqlalchemy import or_ -PLUGIN_DIR = os.path.dirname(__file__) - - def setup_plugin(): config = pluginapi.get_config('mediagoblin.pluginapi.basic_auth') From 58460a8301a8a654a103929260c6d91e2b376960 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 7 May 2013 08:36:04 -0700 Subject: [PATCH 004/153] moved forgot pw views to basic_auth plugin --- mediagoblin/auth/forms.py | 1 - mediagoblin/auth/lib.py | 2 +- mediagoblin/auth/routing.py | 7 +- mediagoblin/auth/views.py | 145 +-------------- mediagoblin/plugins/basic_auth/forms.py | 20 +++ .../plugins/basic_auth/change_fp.html | 44 +++++ .../plugins/basic_auth/forgot_password.html | 38 ++++ mediagoblin/plugins/basic_auth/views.py | 165 ++++++++++++++++++ .../mediagoblin/auth/forgot_password.html | 2 +- 9 files changed, 272 insertions(+), 152 deletions(-) create mode 100644 mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html create mode 100644 mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html create mode 100644 mediagoblin/plugins/basic_auth/views.py diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index bab0d35e..7a67285b 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -16,7 +16,6 @@ import wtforms -from mediagoblin.tools.mail import normalize_email from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.auth.tools import normalize_user_or_email_field diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 8829995a..6ce23f5b 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -143,7 +143,7 @@ def send_fp_verification_email(user, request): {'username': user.username, 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format( host=request.host, - uri=request.urlgen('mediagoblin.auth.verify_forgot_password'), + uri=request.urlgen('mediagoblin.plugins.basic_auth.verify_forgot_password'), userid=unicode(user.id), fp_verification_key=user.fp_verification_key)}) 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/views.py b/mediagoblin/auth/views.py index 2b3b036a..ec409303 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -15,18 +15,15 @@ # along with this program. If not, see . import uuid -import datetime from mediagoblin import messages, mg_globals from mediagoblin.db.models import User 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 mediagoblin.auth.lib import send_verification_email import mediagoblin.auth as auth -from sqlalchemy import or_ + def email_debug_message(request): """ @@ -203,141 +200,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/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py index 28eb7d0a..65981691 100644 --- a/mediagoblin/plugins/basic_auth/forms.py +++ b/mediagoblin/plugins/basic_auth/forms.py @@ -28,3 +28,23 @@ class LoginForm(wtforms.Form): _('Password'), [wtforms.validators.Required(), wtforms.validators.Length(min=5, max=1024)]) + + +class ForgotPassForm(wtforms.Form): + username = wtforms.TextField( + _('Username or email'), + [wtforms.validators.Required(), + normalize_user_or_email_field()]) + + +class ChangePassForm(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()]) diff --git a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html new file mode 100644 index 00000000..9ce12e13 --- /dev/null +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html @@ -0,0 +1,44 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block mediagoblin_head %} + +{% endblock mediagoblin_head %} + +{% block title -%} + {% trans %}Set your new password{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} +
+ {{ csrf_token }} +
+

{% trans %}Set your new password{% endtrans %}

+ {{ wtforms_util.render_divs(cp_form) }} +
+ +
+
+
+{% endblock %} + diff --git a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html new file mode 100644 index 00000000..98cd9a06 --- /dev/null +++ b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html @@ -0,0 +1,38 @@ +{# +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans %}Recover password{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} +
+ {{ csrf_token }} +
+

{% trans %}Recover password{% endtrans %}

+ {{ wtforms_util.render_divs(fp_form) }} +
+ +
+
+
+{% endblock %} diff --git a/mediagoblin/plugins/basic_auth/views.py b/mediagoblin/plugins/basic_auth/views.py new file mode 100644 index 00000000..69d2c52a --- /dev/null +++ b/mediagoblin/plugins/basic_auth/views.py @@ -0,0 +1,165 @@ +# 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 . +import uuid +import datetime + +import forms as auth_forms +from mediagoblin.tools.response import render_to_response, redirect, render_404 +from mediagoblin.db.models import User +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin import messages +from mediagoblin.auth.views import email_debug_message +from mediagoblin.auth.lib import send_fp_verification_email +from mediagoblin.auth import lib as auth_lib + + + +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/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 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/plugins/basic_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/templates/mediagoblin/auth/forgot_password.html b/mediagoblin/templates/mediagoblin/auth/forgot_password.html index 46aeddef..98cd9a06 100644 --- a/mediagoblin/templates/mediagoblin/auth/forgot_password.html +++ b/mediagoblin/templates/mediagoblin/auth/forgot_password.html @@ -24,7 +24,7 @@ {%- endblock %} {% block mediagoblin_content %} -
{{ csrf_token }}
From 0f3504e35b823f7ab391261e6d9a999bcf655d03 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 13 May 2013 15:48:56 -0700 Subject: [PATCH 005/153] moved normalize_user_or_email_field to auth/tools.py from auth/forms.py --- mediagoblin/plugins/basic_auth/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py index 65981691..fe10d89f 100644 --- a/mediagoblin/plugins/basic_auth/forms.py +++ b/mediagoblin/plugins/basic_auth/forms.py @@ -1,7 +1,7 @@ import wtforms from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ -from mediagoblin.auth.forms import normalize_user_or_email_field +from mediagoblin.auth.tools import normalize_user_or_email_field class RegistrationForm(wtforms.Form): From b56b6b1e77cc01aa1ebebd1c6c594ec79cb4d8c1 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 13 May 2013 15:49:50 -0700 Subject: [PATCH 006/153] changed User model pw_hash field to nullable and added migrations --- mediagoblin/db/migrations.py | 9 +++++++++ mediagoblin/db/models.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 2c553396..1617db48 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -287,3 +287,12 @@ def unique_collections_slug(db): constraint.create() db.commit() + + +@RegisterMigration(11, 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) diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 2b925983..323ed4d7 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -61,7 +61,7 @@ class User(Base, UserMixin): # point. email = Column(Unicode, nullable=False) created = Column(DateTime, nullable=False, default=datetime.datetime.now) - pw_hash = Column(Unicode, nullable=False) + pw_hash = Column(Unicode) 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 From 744f1c83b9c94a82612c981ec56782f3db457357 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 14 May 2013 16:14:19 -0700 Subject: [PATCH 007/153] add a check for authentication plugin on startup and respond according to no_auth config option. allows instance to be run w/o authentication --- mediagoblin.ini | 4 +++ mediagoblin/app.py | 4 +++ mediagoblin/auth/tools.py | 22 ++++++++++++ mediagoblin/auth/views.py | 13 +++++-- mediagoblin/plugins/basic_auth/__init__.py | 5 +++ mediagoblin/templates/mediagoblin/base.html | 2 +- .../mediagoblin/bits/frontpage_welcome.html | 36 +++++++++++-------- .../mediagoblin/user_pages/media.html | 2 +- mediagoblin/tools/template.py | 1 + 9 files changed, 70 insertions(+), 19 deletions(-) diff --git a/mediagoblin.ini b/mediagoblin.ini index 4906546a..27146845 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -33,6 +33,10 @@ allow_registration = true ## install other themes. # theme = airy +# Set to true to run an instance with no authentication plugins enabled. +# You will not be able to login or register +no_auth = false + [storage:queuestore] base_dir = %(here)s/user_dev/media/queue diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 1984ce77..51c597aa 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -37,6 +37,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 _log = logging.getLogger(__name__) @@ -97,6 +98,9 @@ class MediaGoblinApp(object): PluginManager().get_template_paths() ) + # Check if authentication plugin is enabled and respond accordingly. + self.auth = check_auth_enabled() + # Set up storage systems self.public_store, self.queue_store = setup_storage() diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 1b30a7d9..114cc7fb 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -14,10 +14,16 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import logging +import sys import wtforms +from mediagoblin import mg_globals from mediagoblin.tools.mail import normalize_email from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.tools.pluginapi import hook_handle + +_log = logging.getLogger(__name__) def normalize_user_or_email_field(allow_email=True, allow_user=True): @@ -48,3 +54,19 @@ def normalize_user_or_email_field(allow_email=True, allow_user=True): if field.data is None: # should not happen, but be cautious anyway raise wtforms.ValidationError(message) return _normalize_field + + +def check_auth_enabled(): + no_auth = mg_globals.app_config['no_auth'] + auth_plugin = True if hook_handle('auth') is not None else False + + if no_auth == 'false' and not auth_plugin: + print 'No authentication plugin is enabled and no_auth = false in ' \ + 'config! \n..Exiting' + sys.exit() + + if no_auth == 'true' and not auth_plugin: + _log.warning('No authentication is enabled') + return False + else: + return True diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index ec409303..811bb157 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -44,8 +44,9 @@ def register(request): 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"]: + # Redirects to indexpage if registrations are disabled or no authentication + # is enabled + if not mg_globals.app_config["allow_registration"] or not mg_globals.app.auth: messages.add_message( request, messages.WARNING, @@ -88,6 +89,14 @@ def login(request): If you provide the POST with 'next', it'll redirect to that view. """ + # Redirects to index page if no authentication is enabled + if not mg_globals.app.auth: + messages.add_message( + request, + messages.WARNING, + _('Sorry, authentication is disabled on this instance.')) + return redirect(request, 'index') + login_form = auth.get_login_form(request) login_failed = False diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 6500151a..a3539738 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -81,8 +81,13 @@ def get_registration_form(request): return auth_forms.RegistrationForm(request.form) +def auth(): + return True + + hooks = { 'setup': setup_plugin, + 'auth': auth, 'auth_check_login': check_login, 'auth_get_user': get_user, 'auth_create_user': create_user, diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html index 5e2898f9..d9ef34ae 100644 --- a/mediagoblin/templates/mediagoblin/base.html +++ b/mediagoblin/templates/mediagoblin/base.html @@ -67,7 +67,7 @@ {% trans %}Verify your email!{% endtrans %} or {% trans %}log out{% endtrans %} {% endif %} - {%- else %} + {%- elif auth %} {%- trans %}Log in{% endtrans -%} diff --git a/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html b/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html index 544ee146..26153694 100644 --- a/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html +++ b/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html @@ -17,19 +17,25 @@ #} {% if request.user %} -

{% trans %}Explore{% endtrans %}

-{% else %} -

{% trans %}Hi there, welcome to this MediaGoblin site!{% endtrans %}

- -

{% trans %}This site is running MediaGoblin, an extraordinarily great piece of media hosting software.{% endtrans %}

-

{% trans %}To add your own media, place comments, and more, you can log in with your MediaGoblin account.{% endtrans %}

- {% if allow_registration %} -

{% trans %}Don't have one yet? It's easy!{% endtrans %}

- {% trans register_url=request.urlgen('mediagoblin.auth.register') -%} - Create an account at this site - or - Set up MediaGoblin on your own server - {%- endtrans %} +

{% trans %}Explore{% endtrans %}

+ {% else %} +

{% trans %}Hi there, welcome to this MediaGoblin site!{% endtrans %}

+ +

{% trans %}This site is running MediaGoblin, an extraordinarily great piece of media hosting software.{% endtrans %}

+ {% if auth %} +

{% trans %}To add your own media, place comments, and more, you can log in with your MediaGoblin account.{% endtrans %}

+ {% if allow_registration %} +

{% trans %}Don't have one yet? It's easy!{% endtrans %}

+ {% trans register_url=request.urlgen('mediagoblin.auth.register') -%} + Create an account at this site + or + {%- endtrans %} + {% endif %} + {% endif %} + {% trans %} + Set up MediaGoblin on your own server + {%- endtrans %} + +
{% endif %} -
-{% endif %} + diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 92c01c48..08e9d8ea 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -86,7 +86,7 @@

{{ media.description_html }}

{% endautoescape %} {% if comments %} - {% if app_config['allow_comments'] %} + {% if app_config['allow_comments'] and auth %} Date: Tue, 14 May 2013 17:14:48 -0700 Subject: [PATCH 008/153] moved bcrypt_check_password to basic_auth/tools from auth/lib --- mediagoblin/auth/__init__.py | 4 +-- mediagoblin/auth/lib.py | 32 ---------------------- mediagoblin/auth/views.py | 2 +- mediagoblin/db/mixin.py | 5 ++-- mediagoblin/edit/views.py | 1 + mediagoblin/plugins/basic_auth/__init__.py | 5 ++-- 6 files changed, 9 insertions(+), 40 deletions(-) diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index 2460c048..abb18d2d 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -16,8 +16,8 @@ from mediagoblin.tools.pluginapi import hook_handle -def check_login(user, login_form): - return hook_handle("auth_check_login", user, login_form) +def check_login(user, password): + return hook_handle("auth_check_login", user, password) def get_user(*args): diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 6ce23f5b..1a9416fc 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -23,38 +23,6 @@ from mediagoblin.tools.template import render_template from mediagoblin import mg_globals -def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): - """ - Check to see if this password matches. - - Args: - - raw_pass: user submitted password to check for authenticity. - - stored_hash: The hash of the raw password (and possibly extra - salt) to check against - - extra_salt: (optional) If this password is with stored with a - non-database extra salt (probably in the config file) for extra - security, factor this into the check. - - Returns: - True or False depending on success. - """ - if extra_salt: - raw_pass = u"%s:%s" % (extra_salt, raw_pass) - - hashed_pass = bcrypt.hashpw(raw_pass.encode('utf-8'), stored_hash) - - # Reduce risk of timing attacks by hashing again with a random - # number (thx to zooko on this advice, which I hopefully - # incorporated right.) - # - # See also: - rand_salt = bcrypt.gensalt(5) - randplus_stored_hash = bcrypt.hashpw(stored_hash, rand_salt) - randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt) - - return randplus_stored_hash == randplus_hashed_pass - - def bcrypt_gen_password_hash(raw_pass, extra_salt=None): """ Generate a salt for this new password. diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 811bb157..b13efebc 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -105,7 +105,7 @@ def login(request): if login_form.validate(): user = auth.get_user(login_form) - if user and auth.check_login(user, login_form): + if user and auth.check_login(user, login_form.password.data): # set up login in session request.session['user_id'] = unicode(user.id) request.session.save() diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index e7f66fa1..2f41292b 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -34,7 +34,7 @@ import datetime from werkzeug.utils import cached_property from mediagoblin import mg_globals -from mediagoblin.auth import lib as auth_lib +from mediagoblin import auth from mediagoblin.media_types import get_media_managers, FileTypeNotSupported from mediagoblin.tools import common, licenses from mediagoblin.tools.text import cleaned_markdown_conversion @@ -46,8 +46,7 @@ class UserMixin(object): """ See if a user can login with this password """ - return auth_lib.bcrypt_check_password( - password, self.pw_hash) + return auth.check_login(self, password) @property def bio_html(self): diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 508c380d..ad3cbaca 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -23,6 +23,7 @@ from mediagoblin import messages from mediagoblin import mg_globals from mediagoblin.auth import lib as auth_lib +from mediagoblin import auth from mediagoblin.edit import forms from mediagoblin.edit.lib import may_edit_media from mediagoblin.decorators import (require_active_login, active_user_from_url, diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index a3539738..68e331ff 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -17,6 +17,7 @@ import os import uuid import forms as auth_forms +import tools as auth_tools from mediagoblin.auth import lib as auth_lib from mediagoblin.db.models import User from mediagoblin.tools.translate import pass_to_ugettext as _ @@ -28,8 +29,8 @@ def setup_plugin(): config = pluginapi.get_config('mediagoblin.pluginapi.basic_auth') -def check_login(user, login_form): - return user.check_login(login_form.password.data) +def check_login(user, password): + return auth_tools.bcrypt_check_password(password, user.pw_hash) def get_user(login_form): From 9c2c9be79d210155f1b8f299d34029afe3a434ed Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 14 May 2013 17:38:18 -0700 Subject: [PATCH 009/153] moved bcrypt_gen_password_hash to basic_auth/tools and added gen_password_hash function to auth/__init__ --- mediagoblin/auth/__init__.py | 4 ++++ mediagoblin/auth/lib.py | 16 ---------------- mediagoblin/edit/views.py | 1 - mediagoblin/gmg_commands/users.py | 6 +++--- mediagoblin/plugins/basic_auth/__init__.py | 8 ++++++-- 5 files changed, 13 insertions(+), 22 deletions(-) diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index abb18d2d..4bbecc16 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -42,3 +42,7 @@ def get_login_form(request): def get_registration_form(request): return hook_handle("auth_get_registration_form", request) + + +def gen_password_hash(raw_pass, extra_salt=None): + return hook_handle("auth_gen_password_hash", raw_pass, extra_salt) diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 1a9416fc..45d0a63f 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -23,22 +23,6 @@ from mediagoblin.tools.template import render_template from mediagoblin import mg_globals -def bcrypt_gen_password_hash(raw_pass, extra_salt=None): - """ - Generate a salt for this new password. - - Args: - - raw_pass: user submitted password - - extra_salt: (optional) If this password is with stored with a - non-database extra salt - """ - if extra_salt: - raw_pass = u"%s:%s" % (extra_salt, raw_pass) - - return unicode( - bcrypt.hashpw(raw_pass.encode('utf-8'), bcrypt.gensalt())) - - def fake_login_attempt(): """ Pretend we're trying to login. diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index ad3cbaca..9db1c3f9 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -22,7 +22,6 @@ 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 import auth from mediagoblin.edit import forms from mediagoblin.edit.lib import may_edit_media diff --git a/mediagoblin/gmg_commands/users.py b/mediagoblin/gmg_commands/users.py index 024c8498..1f329459 100644 --- a/mediagoblin/gmg_commands/users.py +++ b/mediagoblin/gmg_commands/users.py @@ -15,7 +15,7 @@ # along with this program. If not, see . 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): @@ -52,7 +52,7 @@ 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.pw_hash = auth.gen_password_hash(args.password) entry.status = u'active' entry.email_verified = True entry.save() @@ -96,7 +96,7 @@ def changepw(args): user = db.User.one({'username': unicode(args.username.lower())}) if user: - user.pw_hash = auth_lib.bcrypt_gen_password_hash(args.password) + user.pw_hash = auth.gen_password_hash(args.password) user.save() print 'Password successfully changed' else: diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 68e331ff..f11d255a 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -18,7 +18,6 @@ import uuid import forms as auth_forms import tools as auth_tools -from mediagoblin.auth import lib as auth_lib from mediagoblin.db.models import User from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools import pluginapi @@ -47,7 +46,7 @@ def create_user(registration_form): user = User() user.username = registration_form.data['username'] user.email = registration_form.data['email'] - user.pw_hash = auth_lib.bcrypt_gen_password_hash( + user.pw_hash = auth_tools.bcrypt_gen_password_hash( registration_form.password.data) user.verification_key = unicode(uuid.uuid4()) user.save() @@ -82,6 +81,10 @@ def get_registration_form(request): return auth_forms.RegistrationForm(request.form) +def gen_password_hash(raw_pass, extra_salt): + return auth_tools.bcrypt_gen_password_hash(raw_pass, extra_salt) + + def auth(): return True @@ -95,4 +98,5 @@ hooks = { 'auth_extra_validation': extra_validation, 'auth_get_login_form': get_login_form, 'auth_get_registration_form': get_registration_form, + 'auth_gen_password_hash': gen_password_hash, } From 0bd654a346936e8cfd25d678836ae538f50d9f17 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 15 May 2013 12:08:23 -0700 Subject: [PATCH 010/153] modified check_login function to return None instead of False to be able to have multiple plugins check_login --- mediagoblin/auth/__init__.py | 5 ++++- mediagoblin/plugins/basic_auth/__init__.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index 4bbecc16..60cbdb0e 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -17,7 +17,10 @@ from mediagoblin.tools.pluginapi import hook_handle def check_login(user, password): - return hook_handle("auth_check_login", user, password) + result = hook_handle("auth_check_login", user, password) + if result: + return result + return False def get_user(*args): diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index f11d255a..219dd456 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -29,7 +29,10 @@ def setup_plugin(): def check_login(user, password): - return auth_tools.bcrypt_check_password(password, user.pw_hash) + result = auth_tools.bcrypt_check_password(password, user.pw_hash) + if result: + return result + return None def get_user(login_form): From 5b6923ab84118e967d5b39a4f05756bcccb525be Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 15 May 2013 12:44:00 -0700 Subject: [PATCH 011/153] renamed basic_auth/tools to basic_auth/lib --- mediagoblin/plugins/basic_auth/__init__.py | 8 +- mediagoblin/plugins/basic_auth/lib.py | 99 ++++++++++++++++++++++ 2 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 mediagoblin/plugins/basic_auth/lib.py diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 219dd456..0139c78d 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -17,7 +17,7 @@ import os import uuid import forms as auth_forms -import tools as auth_tools +import lib as auth_lib from mediagoblin.db.models import User from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools import pluginapi @@ -29,7 +29,7 @@ def setup_plugin(): def check_login(user, password): - result = auth_tools.bcrypt_check_password(password, user.pw_hash) + result = auth_lib.bcrypt_check_password(password, user.pw_hash) if result: return result return None @@ -49,7 +49,7 @@ def create_user(registration_form): user = User() user.username = registration_form.data['username'] user.email = registration_form.data['email'] - user.pw_hash = auth_tools.bcrypt_gen_password_hash( + user.pw_hash = auth_lib.bcrypt_gen_password_hash( registration_form.password.data) user.verification_key = unicode(uuid.uuid4()) user.save() @@ -85,7 +85,7 @@ def get_registration_form(request): def gen_password_hash(raw_pass, extra_salt): - return auth_tools.bcrypt_gen_password_hash(raw_pass, extra_salt) + return auth_lib.bcrypt_gen_password_hash(raw_pass, extra_salt) def auth(): diff --git a/mediagoblin/plugins/basic_auth/lib.py b/mediagoblin/plugins/basic_auth/lib.py new file mode 100644 index 00000000..57820003 --- /dev/null +++ b/mediagoblin/plugins/basic_auth/lib.py @@ -0,0 +1,99 @@ +# 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 . +import bcrypt + +from mediagoblin.tools.template import render_template +from mediagoblin.tools.mail import send_email +from mediagoblin import mg_globals + + +def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): + """ + Check to see if this password matches. + + Args: + - raw_pass: user submitted password to check for authenticity. + - stored_hash: The hash of the raw password (and possibly extra + salt) to check against + - extra_salt: (optional) If this password is with stored with a + non-database extra salt (probably in the config file) for extra + security, factor this into the check. + + Returns: + True or False depending on success. + """ + if extra_salt: + raw_pass = u"%s:%s" % (extra_salt, raw_pass) + + hashed_pass = bcrypt.hashpw(raw_pass.encode('utf-8'), stored_hash) + + # Reduce risk of timing attacks by hashing again with a random + # number (thx to zooko on this advice, which I hopefully + # incorporated right.) + # + # See also: + rand_salt = bcrypt.gensalt(5) + randplus_stored_hash = bcrypt.hashpw(stored_hash, rand_salt) + randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt) + + return randplus_stored_hash == randplus_hashed_pass + + +def bcrypt_gen_password_hash(raw_pass, extra_salt=None): + """ + Generate a salt for this new password. + + Args: + - raw_pass: user submitted password + - extra_salt: (optional) If this password is with stored with a + non-database extra salt + """ + if extra_salt: + raw_pass = u"%s:%s" % (extra_salt, raw_pass) + + return unicode( + bcrypt.hashpw(raw_pass.encode('utf-8'), bcrypt.gensalt())) + + +EMAIL_FP_VERIFICATION_TEMPLATE = ( + u"http://{host}{uri}?" + u"userid={userid}&token={fp_verification_key}") + + +def send_fp_verification_email(user, request): + """ + Send the verification email to users to change their password. + + Args: + - user: a user object + - request: the request + """ + rendered_email = render_template( + request, 'mediagoblin/auth/fp_verification_email.txt', + {'username': user.username, + 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format( + host=request.host, + uri=request.urlgen('mediagoblin.plugins.' + + 'basic_auth.verify_forgot_password'), + userid=unicode(user.id), + fp_verification_key=user.fp_verification_key)}) + + # TODO: There is no error handling in place + send_email( + mg_globals.app_config['email_sender_address'], + [user.email], + 'GNU MediaGoblin - Change forgotten password!', + rendered_email) From f65615eaf9bd01786ae91c21103b7b3ef921896f Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 15 May 2013 13:24:43 -0700 Subject: [PATCH 012/153] renamed hook as to no conflict with existing hook names --- mediagoblin/auth/tools.py | 2 +- mediagoblin/plugins/basic_auth/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 114cc7fb..f06182b2 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -58,7 +58,7 @@ def normalize_user_or_email_field(allow_email=True, allow_user=True): def check_auth_enabled(): no_auth = mg_globals.app_config['no_auth'] - auth_plugin = True if hook_handle('auth') is not None else False + auth_plugin = True if hook_handle('authentication') is not None else False if no_auth == 'false' and not auth_plugin: print 'No authentication plugin is enabled and no_auth = false in ' \ diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 0139c78d..db5229a8 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -94,7 +94,7 @@ def auth(): hooks = { 'setup': setup_plugin, - 'auth': auth, + 'authentication': auth, 'auth_check_login': check_login, 'auth_get_user': get_user, 'auth_create_user': create_user, From fa7232913c42fe242e07060f0f42ff546f6d68cc Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 15 May 2013 15:56:05 -0700 Subject: [PATCH 013/153] modified test .ini files and changed tests to use basic_auth bcrypt --- mediagoblin/tests/appconfig_context_modified.ini | 1 + mediagoblin/tests/appconfig_plugin_specs.ini | 4 ++++ mediagoblin/tests/test_edit.py | 3 ++- mediagoblin/tests/test_mgoblin_app.ini | 2 ++ mediagoblin/tests/tools.py | 4 ++-- 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/mediagoblin/tests/appconfig_context_modified.ini b/mediagoblin/tests/appconfig_context_modified.ini index 80ca69b1..23efa3bd 100644 --- a/mediagoblin/tests/appconfig_context_modified.ini +++ b/mediagoblin/tests/appconfig_context_modified.ini @@ -2,6 +2,7 @@ direct_remote_path = /test_static/ email_sender_address = "notice@mediagoblin.example.org" email_debug_mode = true +no_auth = true # TODO: Switch to using an in-memory database sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db" diff --git a/mediagoblin/tests/appconfig_plugin_specs.ini b/mediagoblin/tests/appconfig_plugin_specs.ini index 5511cd97..2029aa81 100644 --- a/mediagoblin/tests/appconfig_plugin_specs.ini +++ b/mediagoblin/tests/appconfig_plugin_specs.ini @@ -12,6 +12,10 @@ email_debug_mode = true # Set to false to disable registrations allow_registration = true +# Set to true to run an instance with no authentication plugins enabled. +# You will not be able to login or register +no_auth = true + [plugins] [[mediagoblin.tests.testplugins.pluginspec]] some_string = "not blork" diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py index 08b4f8cf..ccdf9c29 100644 --- a/mediagoblin/tests/test_edit.py +++ b/mediagoblin/tests/test_edit.py @@ -21,7 +21,8 @@ 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.plugins.basic_auth.lib import bcrypt_check_password + class TestUserEdit(object): def setup(self): diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index 0466b53b..180eea19 100644 --- a/mediagoblin/tests/test_mgoblin_app.ini +++ b/mediagoblin/tests/test_mgoblin_app.ini @@ -2,6 +2,7 @@ direct_remote_path = /test_static/ email_sender_address = "notice@mediagoblin.example.org" email_debug_mode = true +no_auth = true # TODO: Switch to using an in-memory database sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db" @@ -31,3 +32,4 @@ BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db" [[mediagoblin.plugins.oauth]] [[mediagoblin.plugins.httpapiauth]] [[mediagoblin.plugins.piwigo]] +[[mediagoblin.plugins.basic_auth]] diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py index 2ee39e89..35c2c3e9 100644 --- a/mediagoblin/tests/tools.py +++ b/mediagoblin/tests/tools.py @@ -31,7 +31,7 @@ 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 @@ -179,7 +179,7 @@ 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) + test_user.pw_hash = gen_password_hash(password) if active_user: test_user.email_verified = True test_user.status = u'active' From 7a98eb73d9f1b05cc34e4780707498f16f1d010b Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 16 May 2013 19:01:45 -0700 Subject: [PATCH 014/153] existing test all passing now --- mediagoblin/tests/basic_auth_appconfig.ini | 28 ++++ mediagoblin/tests/test_auth.py | 121 --------------- mediagoblin/tests/test_basic_auth.py | 166 +++++++++++++++++++++ 3 files changed, 194 insertions(+), 121 deletions(-) create mode 100644 mediagoblin/tests/basic_auth_appconfig.ini create mode 100644 mediagoblin/tests/test_basic_auth.py diff --git a/mediagoblin/tests/basic_auth_appconfig.ini b/mediagoblin/tests/basic_auth_appconfig.ini new file mode 100644 index 00000000..b15ae1fb --- /dev/null +++ b/mediagoblin/tests/basic_auth_appconfig.ini @@ -0,0 +1,28 @@ +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true +no_auth = false + +# TODO: Switch to using an in-memory database +sql_engine = "sqlite:///%(here)s/test_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/test_user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/test_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" + +[plugins] +[[mediagoblin.plugins.basic_auth]] + diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index 755727f9..a9165340 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -15,54 +15,13 @@ # along with this program. If not, see . import urlparse -import datetime 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.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') - - def test_register_views(test_app): """ Massive test function that all our registration-related views all work. @@ -210,86 +169,6 @@ def test_register_views(test_app): ## TODO: Also check for double instances of an email address? - ### Oops, forgot the password - # ------------------- - template.clear_test_template_context() - response = test_app.post( - '/auth/forgot_password/', - {'username': u'happygirl'}) - response.follow() - - ## Did we redirect to the proper page? Use the right template? - assert urlparse.urlsplit(response.location)[2] == '/auth/login/' - assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT - - ## 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' - email_context = template.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/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 - - ## 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" - - ## 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() - - ## 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 - - ## 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', - 'token': parsed_get_params['token']}) - response.follow() - assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT - - ## Verify step 2.2 of password-change works -- login w/ new password success - template.clear_test_template_context() - response = test_app.post( - '/auth/login/', { - 'username': u'happygirl', - 'password': 'iamveryveryhappy'}) - - # User should be redirected - response.follow() - assert urlparse.urlsplit(response.location)[2] == '/' - assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT - def test_authentication_views(test_app): """ diff --git a/mediagoblin/tests/test_basic_auth.py b/mediagoblin/tests/test_basic_auth.py new file mode 100644 index 00000000..20098ab7 --- /dev/null +++ b/mediagoblin/tests/test_basic_auth.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 . +import urlparse +import datetime +import pkg_resources +import pytest + +from mediagoblin.plugins.basic_auth import lib as auth_lib +from mediagoblin import mg_globals +from mediagoblin.tools import template, mail +from mediagoblin.tests.tools import get_app, fixture_add_user +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_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') + + +@pytest.fixture() +def context_modified_app(request): + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'mediagoblin.tests', 'basic_auth_appconfig.ini')) + + +def test_fp_view(context_modified_app): + ### Oops, forgot the password + # ------------------- + ## Register a user + fixture_add_user(active_user=True) + + template.clear_test_template_context() + response = context_modified_app.post( + '/auth/forgot_password/', + {'username': u'chris'}) + response.follow() + + ## Did we redirect to the proper page? Use the right template? + assert urlparse.urlsplit(response.location)[2] == '/auth/login/' + assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT + + ## 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'] == 'chris@example.com' + email_context = template.TEMPLATE_TEST_CONTEXT[ + 'mediagoblin/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'chris'}) + 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 + + ## Try using a bs password-changing verification key, shouldn't work + template.clear_test_template_context() + response = context_modified_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" + + ## 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'chris'}) + real_token_expiration = new_user.fp_token_expire + new_user.fp_token_expire = datetime.datetime.now() + new_user.save() + response = context_modified_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() + + ## Verify step 1 of password-change works -- can see form to + ## change password + template.clear_test_template_context() + response = context_modified_app.get("%s?%s" % (path, get_params)) + 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 = context_modified_app.post( + '/auth/forgot_password/verify/', { + 'userid': parsed_get_params['userid'], + 'password': 'iamveryveryhappy', + 'token': parsed_get_params['token']}) + response.follow() + assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT + + ## Verify step 2.2 of password-change works -- login w/ new password + ## success + template.clear_test_template_context() + response = context_modified_app.post( + '/auth/login/', { + 'username': u'chris', + 'password': 'iamveryveryhappy'}) + + # User should be redirected + response.follow() + assert urlparse.urlsplit(response.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT From f644293ea8768b82391394388067678c8e70ea0a Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 17 May 2013 07:51:08 -0700 Subject: [PATCH 015/153] changed from sys.exit() to raise AuthError for handling no_auth=false in config and no auth plugin present --- mediagoblin/auth/tools.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index f06182b2..bd171261 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -15,7 +15,6 @@ # along with this program. If not, see . import logging -import sys import wtforms from mediagoblin import mg_globals @@ -56,14 +55,21 @@ def normalize_user_or_email_field(allow_email=True, allow_user=True): return _normalize_field +class AuthError(Exception): + def __init__(self): + self.value = 'No Authentication Plugin is enabled and no_auth = false'\ + ' in config!' + + def __str__(self): + return repr(self.value) + + def check_auth_enabled(): no_auth = mg_globals.app_config['no_auth'] auth_plugin = True if hook_handle('authentication') is not None else False if no_auth == 'false' and not auth_plugin: - print 'No authentication plugin is enabled and no_auth = false in ' \ - 'config! \n..Exiting' - sys.exit() + raise AuthError if no_auth == 'true' and not auth_plugin: _log.warning('No authentication is enabled') From dfd3f561af07e5108317992f6ae836858e3cd0bf Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 17 May 2013 10:20:46 -0700 Subject: [PATCH 016/153] added tests for no_auth feature --- mediagoblin/tests/auth_configs/__init__.py | 0 .../auth_configs/basic_auth_appconfig.ini | 28 ++++++++++ ...no_auth_false_no_auth_plugin_appconfig.ini | 27 +++++++++ .../no_auth_true_no_auth_plugin_appconfig.ini | 27 +++++++++ mediagoblin/tests/test_auth.py | 56 ++++++++++++++++++- mediagoblin/tests/test_basic_auth.py | 4 +- 6 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 mediagoblin/tests/auth_configs/__init__.py create mode 100644 mediagoblin/tests/auth_configs/basic_auth_appconfig.ini create mode 100644 mediagoblin/tests/auth_configs/no_auth_false_no_auth_plugin_appconfig.ini create mode 100644 mediagoblin/tests/auth_configs/no_auth_true_no_auth_plugin_appconfig.ini diff --git a/mediagoblin/tests/auth_configs/__init__.py b/mediagoblin/tests/auth_configs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini b/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini new file mode 100644 index 00000000..b15ae1fb --- /dev/null +++ b/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini @@ -0,0 +1,28 @@ +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true +no_auth = false + +# TODO: Switch to using an in-memory database +sql_engine = "sqlite:///%(here)s/test_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/test_user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/test_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" + +[plugins] +[[mediagoblin.plugins.basic_auth]] + diff --git a/mediagoblin/tests/auth_configs/no_auth_false_no_auth_plugin_appconfig.ini b/mediagoblin/tests/auth_configs/no_auth_false_no_auth_plugin_appconfig.ini new file mode 100644 index 00000000..719ff260 --- /dev/null +++ b/mediagoblin/tests/auth_configs/no_auth_false_no_auth_plugin_appconfig.ini @@ -0,0 +1,27 @@ +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true +no_auth = false + +# TODO: Switch to using an in-memory database +sql_engine = "sqlite:///%(here)s/test_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/test_user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/test_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" + +[plugins] + diff --git a/mediagoblin/tests/auth_configs/no_auth_true_no_auth_plugin_appconfig.ini b/mediagoblin/tests/auth_configs/no_auth_true_no_auth_plugin_appconfig.ini new file mode 100644 index 00000000..6c0d5241 --- /dev/null +++ b/mediagoblin/tests/auth_configs/no_auth_true_no_auth_plugin_appconfig.ini @@ -0,0 +1,27 @@ +[mediagoblin] +direct_remote_path = /test_static/ +email_sender_address = "notice@mediagoblin.example.org" +email_debug_mode = true +no_auth = true + +# TODO: Switch to using an in-memory database +sql_engine = "sqlite:///%(here)s/test_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/test_user_dev/media/public +base_url = /mgoblin_media/ + +[storage:queuestore] +base_dir = %(here)s/test_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" + +[plugins] + diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index a9165340..c67d523f 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -13,13 +13,16 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - +import pkg_resources +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.tests.tools import get_app, fixture_add_user from mediagoblin.tools import template, mail +from mediagoblin.auth.tools import AuthError +from mediagoblin import auth def test_register_views(test_app): @@ -273,3 +276,52 @@ def test_authentication_views(test_app): 'password': 'toast', 'next' : '/u/chris/'}) assert urlparse.urlsplit(response.location)[2] == '/u/chris/' + + +# App with no_auth=false and no auth plugin enabled +def no_auth_false_no_auth_plugin_app(request): + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'mediagoblin.tests.auth_configs', + 'no_auth_false_no_auth_plugin_appconfig.ini')) + + +def test_no_auth_false_no_auth_plugin_raises(request): + with pytest.raises(AuthError): + no_auth_false_no_auth_plugin_app(request) + + +@pytest.fixture() +def no_auth_true_no_auth_plugin_app(request): + return get_app( + request, + mgoblin_config=pkg_resources.resource_filename( + 'mediagoblin.tests.auth_configs', + 'no_auth_true_no_auth_plugin_appconfig.ini')) + + +def test_no_auth_true_no_auth_plugin_app(no_auth_true_no_auth_plugin_app): + # app.auth should = false + assert mg_globals.app.auth is False + + # Try to visit register page + template.clear_test_template_context() + response = no_auth_true_no_auth_plugin_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 = no_auth_true_no_auth_plugin_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 should return False + assert auth.check_login('test', 'simple') is False diff --git a/mediagoblin/tests/test_basic_auth.py b/mediagoblin/tests/test_basic_auth.py index 20098ab7..a985c315 100644 --- a/mediagoblin/tests/test_basic_auth.py +++ b/mediagoblin/tests/test_basic_auth.py @@ -72,15 +72,15 @@ def context_modified_app(request): return get_app( request, mgoblin_config=pkg_resources.resource_filename( - 'mediagoblin.tests', 'basic_auth_appconfig.ini')) + 'mediagoblin.tests.auth_configs', 'basic_auth_appconfig.ini')) def test_fp_view(context_modified_app): ### Oops, forgot the password - # ------------------- ## Register a user fixture_add_user(active_user=True) + # ------------------- template.clear_test_template_context() response = context_modified_app.post( '/auth/forgot_password/', From d93cd2684b484f925839574ce3bd6d58137066fa Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 17 May 2013 10:28:43 -0700 Subject: [PATCH 017/153] made basic_auth a default plugin --- mediagoblin.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/mediagoblin.ini b/mediagoblin.ini index 27146845..4799b248 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -51,3 +51,4 @@ base_url = /mgoblin_media/ # documentation for details. [plugins] [[mediagoblin.plugins.geolocation]] +[[mediagoblin.plugins.basic_auth]] From c9dec8b3cc2c2db306256d9eb12cdd44bf96a56c Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 17 May 2013 10:50:46 -0700 Subject: [PATCH 018/153] log a previously logged in user when switched to no_auth mode --- mediagoblin/app.py | 5 ++++- mediagoblin/auth/tools.py | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 51c597aa..982e570c 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -37,7 +37,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 +from mediagoblin.auth.tools import check_auth_enabled, no_auth_logout _log = logging.getLogger(__name__) @@ -192,6 +192,9 @@ class MediaGoblinApp(object): mg_request.setup_user_in_request(request) + # Log user out if in no_auth mode + no_auth_logout(request) + request.controller_name = None try: found_rule, url_values = map_adapter.match(return_rule=True) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index bd171261..7d051a66 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -76,3 +76,9 @@ def check_auth_enabled(): return False else: return True + + +def no_auth_logout(request): + """Log out the user if in no_auth mode""" + if not mg_globals.app.auth: + request.session.delete() From 14efa7bdf19cf4042fe6455c0f9516f5b2d91a0c Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 17 May 2013 11:03:41 -0700 Subject: [PATCH 019/153] moved fake_login_attempt to plugins --- mediagoblin/auth/__init__.py | 4 + mediagoblin/auth/lib.py | 24 ---- mediagoblin/auth/views.py | 140 ++++++++++++++++++++- mediagoblin/plugins/basic_auth/__init__.py | 1 + mediagoblin/plugins/basic_auth/lib.py | 20 +++ mediagoblin/plugins/piwigo/views.py | 4 +- 6 files changed, 166 insertions(+), 27 deletions(-) diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index 60cbdb0e..ffa94212 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -49,3 +49,7 @@ def get_registration_form(request): def gen_password_hash(raw_pass, extra_salt=None): return hook_handle("auth_gen_password_hash", raw_pass, extra_salt) + + +def fake_login_attempt(): + return hook_handle("auth_fake_login_attempt") diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 45d0a63f..6f5340dd 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -13,35 +13,11 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - -import random - -import bcrypt - from mediagoblin.tools.mail import send_email from mediagoblin.tools.template import render_template from mediagoblin import mg_globals -def fake_login_attempt(): - """ - Pretend we're trying to login. - - Nothing actually happens here, we're just trying to take up some - time, approximately the same amount of time as - bcrypt_check_password, so as to avoid figuring out what users are - on the system by intentionally faking logins a bunch of times. - """ - rand_salt = bcrypt.gensalt(5) - - hashed_pass = bcrypt.hashpw(str(random.random()), rand_salt) - - randplus_stored_hash = bcrypt.hashpw(str(random.random()), rand_salt) - randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt) - - randplus_stored_hash == randplus_hashed_pass - - EMAIL_VERIFICATION_TEMPLATE = ( u"http://{host}{uri}?" u"userid={userid}&token={verification_key}") diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index b13efebc..5be4b91b 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -118,7 +118,7 @@ def login(request): # 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() + auth.fake_login_attempt() login_failed = True return render_to_response( @@ -209,3 +209,141 @@ 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/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index db5229a8..c8c3c391 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -102,4 +102,5 @@ hooks = { 'auth_get_login_form': get_login_form, 'auth_get_registration_form': get_registration_form, 'auth_gen_password_hash': gen_password_hash, + 'auth_fake_login_attempt': auth_lib.fake_login_attempt, } diff --git a/mediagoblin/plugins/basic_auth/lib.py b/mediagoblin/plugins/basic_auth/lib.py index 57820003..999abfd9 100644 --- a/mediagoblin/plugins/basic_auth/lib.py +++ b/mediagoblin/plugins/basic_auth/lib.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 . import bcrypt +import random from mediagoblin.tools.template import render_template from mediagoblin.tools.mail import send_email @@ -97,3 +98,22 @@ def send_fp_verification_email(user, request): [user.email], 'GNU MediaGoblin - Change forgotten password!', rendered_email) + + +def fake_login_attempt(): + """ + Pretend we're trying to login. + + Nothing actually happens here, we're just trying to take up some + time, approximately the same amount of time as + bcrypt_check_password, so as to avoid figuring out what users are + on the system by intentionally faking logins a bunch of times. + """ + rand_salt = bcrypt.gensalt(5) + + hashed_pass = bcrypt.hashpw(str(random.random()), rand_salt) + + randplus_stored_hash = bcrypt.hashpw(str(random.random()), rand_salt) + randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt) + + randplus_stored_hash == randplus_hashed_pass diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index 78668ed4..7e3f1076 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -23,7 +23,6 @@ from werkzeug.exceptions import MethodNotAllowed, BadRequest, NotImplemented from werkzeug.wrappers import BaseResponse from mediagoblin.meddleware.csrf import csrf_exempt -from mediagoblin.auth.lib import fake_login_attempt from mediagoblin.media_types import sniff_media from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \ run_process_media, new_upload_entry @@ -33,6 +32,7 @@ from mediagoblin.db.models import Collection from .tools import CmdTable, response_xml, check_form, \ PWGSession, PwgNamedArray, PwgError +from mediagoblin.plugins.basic_auth.lib import fake_login_attempt from .forms import AddSimpleForm, AddForm @@ -126,7 +126,7 @@ def pwg_images_addSimple(request): dump = [] for f in form: dump.append("%s=%r" % (f.name, f.data)) - _log.info("addSimple: %r %s %r", request.form, " ".join(dump), + _log.info("addSimple: %r %s %r", request.form, " ".join(dump), request.files) if not check_file_field(request, 'image'): From ba016fda9af97c4c584f6c5be55aef6082353ec2 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 17 May 2013 13:06:46 -0700 Subject: [PATCH 020/153] added Copyright header to basic_auth/forms.py --- mediagoblin/plugins/basic_auth/forms.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mediagoblin/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py index fe10d89f..5f9dc127 100644 --- a/mediagoblin/plugins/basic_auth/forms.py +++ b/mediagoblin/plugins/basic_auth/forms.py @@ -1,3 +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 . import wtforms from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ From 20583e8a4de3987e499dec730d7e7e1a22e69b3d Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 20 May 2013 07:45:17 -0700 Subject: [PATCH 021/153] removed check_login from db mixin --- mediagoblin/db/mixin.py | 7 ------- mediagoblin/plugins/httpapiauth/__init__.py | 3 ++- mediagoblin/plugins/piwigo/views.py | 3 ++- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index 2f41292b..9f566e36 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -34,7 +34,6 @@ import datetime from werkzeug.utils import cached_property from mediagoblin import mg_globals -from mediagoblin import auth from mediagoblin.media_types import get_media_managers, FileTypeNotSupported from mediagoblin.tools import common, licenses from mediagoblin.tools.text import cleaned_markdown_conversion @@ -42,12 +41,6 @@ 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.check_login(self, password) - @property def bio_html(self): return cleaned_markdown_conversion(self.bio) diff --git a/mediagoblin/plugins/httpapiauth/__init__.py b/mediagoblin/plugins/httpapiauth/__init__.py index 99b6a4b0..09c99080 100644 --- a/mediagoblin/plugins/httpapiauth/__init__.py +++ b/mediagoblin/plugins/httpapiauth/__init__.py @@ -19,6 +19,7 @@ import logging from werkzeug.exceptions import Unauthorized from mediagoblin.plugins.api.tools import Auth +from mediagoblin.auth import check_login _log = logging.getLogger(__name__) @@ -42,7 +43,7 @@ class HTTPAuth(Auth): user = request.db.User.query.filter_by( username=unicode(request.authorization['username'])).first() - if user.check_login(request.authorization['password']): + if check_login(user, request.authorization['password']): request.user = user return True else: diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index 7e3f1076..705cdd49 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -33,6 +33,7 @@ from mediagoblin.db.models import Collection from .tools import CmdTable, response_xml, check_form, \ PWGSession, PwgNamedArray, PwgError from mediagoblin.plugins.basic_auth.lib import fake_login_attempt +from mediagoblin.auth import check_login from .forms import AddSimpleForm, AddForm @@ -48,7 +49,7 @@ def pwg_login(request): _log.info("User %r not found", username) fake_login_attempt() return PwgError(999, 'Invalid username/password') - if not user.check_login(password): + if not check_login(user, password): _log.warn("Wrong password for %r", username) return PwgError(999, 'Invalid username/password') _log.info("Logging %r in", username) From c3e3882e39e9830c3b60b2847713aa0419b31a28 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 20 May 2013 08:10:19 -0700 Subject: [PATCH 022/153] modified auth/__init__ hooks to work better with multiple plugins. Removed auth/lib.py. And added a basic_extra_verification function that all plugins will use. --- mediagoblin/auth/__init__.py | 22 +++++----- mediagoblin/auth/lib.py | 83 ------------------------------------ mediagoblin/auth/tools.py | 65 ++++++++++++++++++++++++++-- 3 files changed, 74 insertions(+), 96 deletions(-) delete mode 100644 mediagoblin/auth/lib.py diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index ffa94212..3966ecd3 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from mediagoblin.tools.pluginapi import hook_handle +from mediagoblin.tools.pluginapi import hook_handle, hook_runall def check_login(user, password): @@ -23,20 +23,22 @@ def check_login(user, password): return False -def get_user(*args): - return hook_handle("auth_get_user", *args) +def get_user(form): + return hook_handle("auth_get_user", form) -def create_user(*args): - return hook_handle("auth_create_user", *args) +def create_user(register_form): + results = hook_runall("auth_create_user", register_form) + return results[0] -def extra_validation(register_form, *args): - return hook_handle("auth_extra_validation", register_form, *args) +def extra_validation(register_form): + from mediagoblin.auth.tools import basic_extra_validation - -def get_user_metadata(user): - return hook_handle("auth_get_user_metadata", user) + 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 get_login_form(request): diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py deleted file mode 100644 index 6f5340dd..00000000 --- a/mediagoblin/auth/lib.py +++ /dev/null @@ -1,83 +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 . -from mediagoblin.tools.mail import send_email -from mediagoblin.tools.template import render_template -from mediagoblin import mg_globals - - -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}") - - -def send_fp_verification_email(user, request): - """ - Send the verification email to users to change their password. - - Args: - - user: a user object - - request: the request - """ - rendered_email = render_template( - request, 'mediagoblin/auth/fp_verification_email.txt', - {'username': user.username, - 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format( - host=request.host, - uri=request.urlgen('mediagoblin.plugins.basic_auth.verify_forgot_password'), - userid=unicode(user.id), - fp_verification_key=user.fp_verification_key)}) - - # TODO: There is no error handling in place - send_email( - mg_globals.app_config['email_sender_address'], - [user.email], - 'GNU MediaGoblin - Change forgotten password!', - rendered_email) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 7d051a66..10fb6491 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -17,10 +17,14 @@ import logging import wtforms -from mediagoblin import mg_globals -from mediagoblin.tools.mail import normalize_email +from mediagoblin import messages, mg_globals +from mediagoblin.tools.mail import normalize_email, send_email from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +from mediagoblin.tools.template import render_template from mediagoblin.tools.pluginapi import hook_handle +from mediagoblin.tools.response import redirect +from mediagoblin import auth +from mediagoblin.db.models import User _log = logging.getLogger(__name__) @@ -66,7 +70,7 @@ class AuthError(Exception): def check_auth_enabled(): no_auth = mg_globals.app_config['no_auth'] - auth_plugin = True if hook_handle('authentication') is not None else False + auth_plugin = hook_handle('authentication') if no_auth == 'false' and not auth_plugin: raise AuthError @@ -82,3 +86,58 @@ def no_auth_logout(request): """Log out the user if in no_auth mode""" if not mg_globals.app.auth: request.session.delete() + + +def basic_extra_validation(register_form, *args): + 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 + + return extra_validation_passes + + +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) From c94316bff4ad360e99a336889a76d8e75247885c Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 20 May 2013 08:45:04 -0700 Subject: [PATCH 023/153] Modified basic_auth plugin to work with modified auth plugin hooks. Added context variables. Removed basic_auth/tools which was previously renamed to basic_auth/lib. --- mediagoblin/plugins/basic_auth/__init__.py | 57 ++++++++++------------ mediagoblin/plugins/basic_auth/forms.py | 2 +- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index c8c3c391..beb16654 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -19,7 +19,6 @@ import uuid import forms as auth_forms import lib as auth_lib from mediagoblin.db.models import User -from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools import pluginapi from sqlalchemy import or_ @@ -35,8 +34,8 @@ def check_login(user, password): return None -def get_user(login_form): - username = login_form.data['username'] +def get_user(form): + username = form.data['username'] user = User.query.filter( or_( User.username == username, @@ -46,36 +45,18 @@ def get_user(login_form): def create_user(registration_form): - user = User() - user.username = registration_form.data['username'] - user.email = registration_form.data['email'] - user.pw_hash = auth_lib.bcrypt_gen_password_hash( - registration_form.password.data) - user.verification_key = unicode(uuid.uuid4()) - user.save() + user = get_user(registration_form) + if not user: + user = User() + user.username = registration_form.data['username'] + user.email = registration_form.data['email'] + user.pw_hash = auth_lib.bcrypt_gen_password_hash( + registration_form.password.data) + user.verification_key = unicode(uuid.uuid4()) + user.save() return user -def extra_validation(register_form, *args): - 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 - - return extra_validation_passes - - def get_login_form(request): return auth_forms.LoginForm(request.form) @@ -92,15 +73,29 @@ def auth(): return True +def append_to_global_context(context): + context['pass_auth'] = True + return context + + +def add_to_form_context(context): + context['pass_auth_link'] = True + return context + + hooks = { 'setup': setup_plugin, 'authentication': auth, 'auth_check_login': check_login, 'auth_get_user': get_user, 'auth_create_user': create_user, - 'auth_extra_validation': extra_validation, 'auth_get_login_form': get_login_form, 'auth_get_registration_form': get_registration_form, 'auth_gen_password_hash': gen_password_hash, 'auth_fake_login_attempt': auth_lib.fake_login_attempt, + 'template_global_context': append_to_global_context, + ('mediagoblin.plugins.openid.register', + 'mediagoblin/auth/register.html'): add_to_form_context, + ('mediagoblin.plugins.openid.login', + 'mediagoblin/auth/login.html'): add_to_form_context, } diff --git a/mediagoblin/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py index 5f9dc127..8321c227 100644 --- a/mediagoblin/plugins/basic_auth/forms.py +++ b/mediagoblin/plugins/basic_auth/forms.py @@ -26,7 +26,7 @@ class RegistrationForm(wtforms.Form): normalize_user_or_email_field(allow_email=False)]) password = wtforms.PasswordField( _('Password'), - [wtforms.validators.Required(), + [wtforms.validators.Optional(), wtforms.validators.Length(min=5, max=1024)]) email = wtforms.TextField( _('Email address'), From 5784c12d7912fbf415995c737ed0f7afad02e7e0 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 20 May 2013 11:48:40 -0700 Subject: [PATCH 024/153] added a register_user function to be able to use in a plugin's register view, and modified auth/views.register to redirect to openid/register if appropriate. --- mediagoblin/auth/tools.py | 33 ++++++++++++++++++++++++++++++ mediagoblin/auth/views.py | 42 +++++++++++++-------------------------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 10fb6491..a1273d3b 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -108,6 +108,39 @@ def basic_extra_validation(register_form, *args): 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) + + # 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 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.") + + EMAIL_VERIFICATION_TEMPLATE = ( u"http://{host}{uri}?" u"userid={userid}&token={verification_key}") diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 5be4b91b..f6d4d4d1 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -21,21 +21,10 @@ from mediagoblin.db.models import User 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.lib import send_verification_email -import mediagoblin.auth as auth - - -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.auth import forms as auth_forms +from mediagoblin.auth.tools import (send_verification_email, + register_user, email_debug_message) +from mediagoblin import auth def register(request): @@ -53,24 +42,17 @@ def register(request): _('Sorry, registration is disabled on this instance.')) return redirect(request, "index") + if 'pass_auth' not in request.template_env.globals: + if 'openid' in request.template_env.globals: + return redirect(request, 'mediagoblin.plugins.openid.register') + register_form = auth.get_registration_form(request) if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already - extra_validation_passes = auth.extra_validation(register_form) - - if extra_validation_passes: - # Create the user - user = auth.create_user(register_form) - - # 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( @@ -97,6 +79,10 @@ def login(request): _('Sorry, authentication is disabled on this instance.')) return redirect(request, 'index') + if 'pass_auth' not in request.template_env.globals: + if 'openid' in request.template_env.globals: + return redirect(request, 'mediagoblin.plugins.openid.login') + login_form = auth.get_login_form(request) login_failed = False From 94d77e1fc15d8aaa8de3f8cadd7c03fa57c12be4 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 21 May 2013 11:28:56 -0700 Subject: [PATCH 025/153] check if password field present in basic_auth create_user --- mediagoblin/plugins/basic_auth/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index beb16654..8dc2e381 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -46,7 +46,7 @@ def get_user(form): def create_user(registration_form): user = get_user(registration_form) - if not user: + if not user and 'password' in registration_form: user = User() user.username = registration_form.data['username'] user.email = registration_form.data['email'] From 569873d8f0a4d71ff82ba79436ef8ae464d41163 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 13:18:47 -0700 Subject: [PATCH 026/153] changed occurances of form.data['whatever'] to form.whatever.data Conflicts: mediagoblin/plugins/basic_auth/__init__.py mediagoblin/plugins/openid/__init__.py --- mediagoblin/auth/tools.py | 4 ++-- mediagoblin/plugins/basic_auth/__init__.py | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index a1273d3b..ac2f6504 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -90,9 +90,9 @@ def no_auth_logout(request): def basic_extra_validation(register_form, *args): users_with_username = User.query.filter_by( - username=register_form.data['username']).count() + username=register_form.username.data).count() users_with_email = User.query.filter_by( - email=register_form.data['email']).count() + email=register_form.email.data).count() extra_validation_passes = True diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 8dc2e381..74d6b836 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -35,21 +35,22 @@ def check_login(user, password): def get_user(form): - username = form.data['username'] - user = User.query.filter( - or_( - User.username == username, - User.email == username, - )).first() - return user + if 'username' in form.data: + username = form.username.data + user = User.query.filter( + or_( + User.username == username, + User.email == username, + )).first() + return user def create_user(registration_form): user = get_user(registration_form) if not user and 'password' in registration_form: user = User() - user.username = registration_form.data['username'] - user.email = registration_form.data['email'] + user.username = registration_form.username.data + user.email = registration_form.email.data user.pw_hash = auth_lib.bcrypt_gen_password_hash( registration_form.password.data) user.verification_key = unicode(uuid.uuid4()) From 09ae2df4eb6b7384403beb323d757fd0f6a81eba Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 13:20:13 -0700 Subject: [PATCH 027/153] modified basic_auth.check_login to check that the user has a pw_hash first --- mediagoblin/plugins/basic_auth/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 74d6b836..d0545627 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -28,9 +28,10 @@ def setup_plugin(): def check_login(user, password): - result = auth_lib.bcrypt_check_password(password, user.pw_hash) - if result: - return result + if user.pw_hash: + result = auth_lib.bcrypt_check_password(password, user.pw_hash) + if result: + return result return None From 57e8be21bcd832a36fbc8feac03dba941ef4d370 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 13:22:13 -0700 Subject: [PATCH 028/153] added focus to form input Conflicts: mediagoblin/auth/views.py mediagoblin/plugins/openid/views.py --- mediagoblin/auth/views.py | 6 +++++- mediagoblin/templates/mediagoblin/auth/change_fp.html | 3 ++- mediagoblin/templates/mediagoblin/auth/forgot_password.html | 2 ++ mediagoblin/templates/mediagoblin/auth/login.html | 2 ++ mediagoblin/templates/mediagoblin/auth/register.html | 4 ++-- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index f6d4d4d1..5a360bd0 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -62,7 +62,9 @@ def register(request): return render_to_response( request, 'mediagoblin/auth/register.html', - {'register_form': register_form}) + {'register_form': register_form, + 'focus': 'username', + 'post_url': request.urlgen('mediagoblin.auth.register')}) def login(request): @@ -113,6 +115,8 @@ def login(request): {'login_form': login_form, 'next': request.GET.get('next') or request.form.get('next'), 'login_failed': login_failed, + 'focus': 'username', + 'post_url': request.urlgen('mediagoblin.auth.login'), 'allow_registration': mg_globals.app_config["allow_registration"]}) diff --git a/mediagoblin/templates/mediagoblin/auth/change_fp.html b/mediagoblin/templates/mediagoblin/auth/change_fp.html index 1f7d9aca..afffeadd 100644 --- a/mediagoblin/templates/mediagoblin/auth/change_fp.html +++ b/mediagoblin/templates/mediagoblin/auth/change_fp.html @@ -39,6 +39,7 @@
- + + {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/auth/forgot_password.html b/mediagoblin/templates/mediagoblin/auth/forgot_password.html index 98cd9a06..6a74e2a2 100644 --- a/mediagoblin/templates/mediagoblin/auth/forgot_password.html +++ b/mediagoblin/templates/mediagoblin/auth/forgot_password.html @@ -35,4 +35,6 @@ + + {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html index 4a39059d..6ec5d343 100644 --- a/mediagoblin/templates/mediagoblin/auth/login.html +++ b/mediagoblin/templates/mediagoblin/auth/login.html @@ -59,4 +59,6 @@ {% endif %} + + {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html index 6dff0207..755d5418 100644 --- a/mediagoblin/templates/mediagoblin/auth/register.html +++ b/mediagoblin/templates/mediagoblin/auth/register.html @@ -42,6 +42,6 @@ - - + + {% endblock %} From b194f29fe3f295b2426fb0ef4809fee6e74c17e7 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 13:28:03 -0700 Subject: [PATCH 029/153] added gen_password_hash and check_password functions to auth/__init__ --- mediagoblin/auth/__init__.py | 5 +++++ mediagoblin/plugins/basic_auth/__init__.py | 5 +++++ mediagoblin/tests/test_edit.py | 6 +++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index 3966ecd3..53182eaa 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -53,5 +53,10 @@ 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) + + def fake_login_attempt(): return hook_handle("auth_fake_login_attempt") diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index d0545627..2d6f7dbd 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -71,6 +71,10 @@ def gen_password_hash(raw_pass, extra_salt): return auth_lib.bcrypt_gen_password_hash(raw_pass, extra_salt) +def check_password(raw_pass, stored_hash, extra_salt): + return auth_lib.bcrypt_check_password(raw_pass, stored_hash, extra_salt) + + def auth(): return True @@ -94,6 +98,7 @@ hooks = { '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_lib.fake_login_attempt, 'template_global_context': append_to_global_context, ('mediagoblin.plugins.openid.register', diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py index ccdf9c29..b6ec7a29 100644 --- a/mediagoblin/tests/test_edit.py +++ b/mediagoblin/tests/test_edit.py @@ -21,7 +21,7 @@ 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.plugins.basic_auth.lib import bcrypt_check_password +from mediagoblin import auth class TestUserEdit(object): @@ -75,7 +75,7 @@ class TestUserEdit(object): # 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) + assert auth.check_password('123456', test_user.pw_hash) # Update current user passwd self.user_password = '123456' @@ -89,7 +89,7 @@ class TestUserEdit(object): }) test_user = User.query.filter_by(username=u'chris').first() - assert not bcrypt_check_password('098765', test_user.pw_hash) + assert not auth.check_password('098765', test_user.pw_hash) def test_change_bio_url(self, test_app): From 9008e09941ee7621fc375edb485120a54abd6ad1 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 13:55:11 -0700 Subject: [PATCH 030/153] fixed failing tests after rebase --- mediagoblin/edit/views.py | 4 ++-- mediagoblin/tests/appconfig_static_plugin.ini | 1 + .../tests/auth_configs/basic_auth_appconfig.ini | 10 +++++----- .../no_auth_false_no_auth_plugin_appconfig.ini | 11 +++++------ .../no_auth_true_no_auth_plugin_appconfig.ini | 11 +++++------ 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 9db1c3f9..161285a2 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -342,7 +342,7 @@ def change_pass(request): if request.method == 'POST' and form.validate(): - if not auth_lib.bcrypt_check_password( + if not auth.check_password( form.old_password.data, user.pw_hash): form.old_password.errors.append( _('Wrong password')) @@ -354,7 +354,7 @@ def change_pass(request): 'user': user}) # Password matches - user.pw_hash = auth_lib.bcrypt_gen_password_hash( + user.pw_hash = auth.gen_password_hash( form.new_password.data) user.save() diff --git a/mediagoblin/tests/appconfig_static_plugin.ini b/mediagoblin/tests/appconfig_static_plugin.ini index dc251171..053a77c1 100644 --- a/mediagoblin/tests/appconfig_static_plugin.ini +++ b/mediagoblin/tests/appconfig_static_plugin.ini @@ -2,6 +2,7 @@ direct_remote_path = /test_static/ email_sender_address = "notice@mediagoblin.example.org" email_debug_mode = true +no_auth = true # TODO: Switch to using an in-memory database sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db" diff --git a/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini b/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini index b15ae1fb..b8c246f4 100644 --- a/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini +++ b/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini @@ -5,23 +5,23 @@ email_debug_mode = true no_auth = false # TODO: Switch to using an in-memory database -sql_engine = "sqlite:///%(here)s/test_user_dev/mediagoblin.db" +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/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_HOST = "sqlite:///%(here)s/user_dev/kombu.db" [plugins] [[mediagoblin.plugins.basic_auth]] diff --git a/mediagoblin/tests/auth_configs/no_auth_false_no_auth_plugin_appconfig.ini b/mediagoblin/tests/auth_configs/no_auth_false_no_auth_plugin_appconfig.ini index 719ff260..49f9e9de 100644 --- a/mediagoblin/tests/auth_configs/no_auth_false_no_auth_plugin_appconfig.ini +++ b/mediagoblin/tests/auth_configs/no_auth_false_no_auth_plugin_appconfig.ini @@ -5,23 +5,22 @@ email_debug_mode = true no_auth = false # TODO: Switch to using an in-memory database -sql_engine = "sqlite:///%(here)s/test_user_dev/mediagoblin.db" +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/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_HOST = "sqlite:///%(here)s/user_dev/kombu.db" [plugins] - diff --git a/mediagoblin/tests/auth_configs/no_auth_true_no_auth_plugin_appconfig.ini b/mediagoblin/tests/auth_configs/no_auth_true_no_auth_plugin_appconfig.ini index 6c0d5241..5e6cfde6 100644 --- a/mediagoblin/tests/auth_configs/no_auth_true_no_auth_plugin_appconfig.ini +++ b/mediagoblin/tests/auth_configs/no_auth_true_no_auth_plugin_appconfig.ini @@ -5,23 +5,22 @@ email_debug_mode = true no_auth = true # TODO: Switch to using an in-memory database -sql_engine = "sqlite:///%(here)s/test_user_dev/mediagoblin.db" +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/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_HOST = "sqlite:///%(here)s/user_dev/kombu.db" [plugins] - From f339b76a4ee04571bd0a94d20a5d53d7f3d8d235 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 18:09:57 -0700 Subject: [PATCH 031/153] moving forgot_password views back to gmg/auth and cleanup --- mediagoblin/auth/routing.py | 7 +- mediagoblin/auth/tools.py | 31 +++- mediagoblin/auth/views.py | 15 +- mediagoblin/plugins/basic_auth/__init__.py | 5 +- mediagoblin/plugins/basic_auth/forms.py | 22 +-- mediagoblin/plugins/basic_auth/lib.py | 35 ---- .../plugins/basic_auth/change_fp.html | 44 ----- .../plugins/basic_auth/forgot_password.html | 38 ---- mediagoblin/plugins/basic_auth/views.py | 165 ------------------ .../mediagoblin/auth/forgot_password.html | 2 +- .../templates/mediagoblin/auth/login.html | 2 + .../auth_configs/basic_auth_appconfig.ini | 28 --- mediagoblin/tests/basic_auth_appconfig.ini | 28 --- mediagoblin/tests/test_auth.py | 92 +++++++++- mediagoblin/tests/test_basic_auth.py | 107 ------------ 15 files changed, 144 insertions(+), 477 deletions(-) delete mode 100644 mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html delete mode 100644 mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html delete mode 100644 mediagoblin/plugins/basic_auth/views.py delete mode 100644 mediagoblin/tests/auth_configs/basic_auth_appconfig.ini delete mode 100644 mediagoblin/tests/basic_auth_appconfig.ini diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 7a688a49..2a6abb47 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -25,4 +25,9 @@ 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.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')] diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index ac2f6504..3e3c36f0 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -22,7 +22,6 @@ from mediagoblin.tools.mail import normalize_email, send_email from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.tools.template import render_template from mediagoblin.tools.pluginapi import hook_handle -from mediagoblin.tools.response import redirect from mediagoblin import auth from mediagoblin.db.models import User @@ -174,3 +173,33 @@ def send_verification_email(user, request): # 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}") + + +def send_fp_verification_email(user, request): + """ + Send the verification email to users to change their password. + + Args: + - user: a user object + - request: the request + """ + rendered_email = render_template( + request, 'mediagoblin/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)}) + + # TODO: There is no error handling in place + send_email( + mg_globals.app_config['email_sender_address'], + [user.email], + 'GNU MediaGoblin - Change forgotten password!', + rendered_email) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 5a360bd0..a21a92e9 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -15,6 +15,7 @@ # along with this program. If not, see . import uuid +import datetime from mediagoblin import messages, mg_globals from mediagoblin.db.models import User @@ -23,7 +24,8 @@ 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.tools import (send_verification_email, - register_user, email_debug_message) + register_user, email_debug_message, + send_fp_verification_email) from mediagoblin import auth @@ -208,13 +210,17 @@ def forgot_password(request): Sends an email with an url to renew forgotten password. Use GET querystring parameter 'username' to pre-populate the input field """ + if not 'pass_auth' in request.template_env.globals: + return redirect(request, 'index') + 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}) + 'mediagoblin/auth/forgot_password.html', {'fp_form': fp_form, + 'focus': 'username'}) # 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 @@ -310,7 +316,8 @@ def verify_forgot_password(request): return render_to_response( request, 'mediagoblin/auth/change_fp.html', - {'cp_form': cp_form}) + {'cp_form': cp_form, + 'focus': 'password'}) # in case there is a valid id but no user with that id in the db # or the token expired @@ -334,6 +341,6 @@ def _process_for_token(request): formdata = { 'vars': formdata_vars, 'has_userid_and_token': - 'userid' in formdata_vars and 'token' in formdata_vars} + 'userid' in formdata_vars and 'token' in formdata_vars} return formdata diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 2d6f7dbd..2fe161cb 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -13,11 +13,10 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import os import uuid -import forms as auth_forms -import lib as auth_lib +from mediagoblin.plugins.basic_auth import forms as auth_forms +from mediagoblin.plugins.basic_auth import lib as auth_lib from mediagoblin.db.models import User from mediagoblin.tools import pluginapi from sqlalchemy import or_ diff --git a/mediagoblin/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py index 8321c227..f389b21e 100644 --- a/mediagoblin/plugins/basic_auth/forms.py +++ b/mediagoblin/plugins/basic_auth/forms.py @@ -26,7 +26,7 @@ class RegistrationForm(wtforms.Form): normalize_user_or_email_field(allow_email=False)]) password = wtforms.PasswordField( _('Password'), - [wtforms.validators.Optional(), + [wtforms.validators.Required(), wtforms.validators.Length(min=5, max=1024)]) email = wtforms.TextField( _('Email address'), @@ -43,23 +43,3 @@ class LoginForm(wtforms.Form): _('Password'), [wtforms.validators.Required(), wtforms.validators.Length(min=5, max=1024)]) - - -class ForgotPassForm(wtforms.Form): - username = wtforms.TextField( - _('Username or email'), - [wtforms.validators.Required(), - normalize_user_or_email_field()]) - - -class ChangePassForm(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()]) diff --git a/mediagoblin/plugins/basic_auth/lib.py b/mediagoblin/plugins/basic_auth/lib.py index 999abfd9..1300bb9a 100644 --- a/mediagoblin/plugins/basic_auth/lib.py +++ b/mediagoblin/plugins/basic_auth/lib.py @@ -16,10 +16,6 @@ import bcrypt import random -from mediagoblin.tools.template import render_template -from mediagoblin.tools.mail import send_email -from mediagoblin import mg_globals - def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None): """ @@ -69,37 +65,6 @@ def bcrypt_gen_password_hash(raw_pass, extra_salt=None): bcrypt.hashpw(raw_pass.encode('utf-8'), bcrypt.gensalt())) -EMAIL_FP_VERIFICATION_TEMPLATE = ( - u"http://{host}{uri}?" - u"userid={userid}&token={fp_verification_key}") - - -def send_fp_verification_email(user, request): - """ - Send the verification email to users to change their password. - - Args: - - user: a user object - - request: the request - """ - rendered_email = render_template( - request, 'mediagoblin/auth/fp_verification_email.txt', - {'username': user.username, - 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format( - host=request.host, - uri=request.urlgen('mediagoblin.plugins.' + - 'basic_auth.verify_forgot_password'), - userid=unicode(user.id), - fp_verification_key=user.fp_verification_key)}) - - # TODO: There is no error handling in place - send_email( - mg_globals.app_config['email_sender_address'], - [user.email], - 'GNU MediaGoblin - Change forgotten password!', - rendered_email) - - def fake_login_attempt(): """ Pretend we're trying to login. diff --git a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html deleted file mode 100644 index 9ce12e13..00000000 --- a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/change_fp.html +++ /dev/null @@ -1,44 +0,0 @@ -{# -# GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 Free Software Foundation, Inc -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -#} -{% extends "mediagoblin/base.html" %} - -{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} - -{% block mediagoblin_head %} - -{% endblock mediagoblin_head %} - -{% block title -%} - {% trans %}Set your new password{% endtrans %} — {{ super() }} -{%- endblock %} - -{% block mediagoblin_content %} -
- {{ csrf_token }} -
-

{% trans %}Set your new password{% endtrans %}

- {{ wtforms_util.render_divs(cp_form) }} -
- -
-
-
-{% endblock %} - diff --git a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html b/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html deleted file mode 100644 index 98cd9a06..00000000 --- a/mediagoblin/plugins/basic_auth/templates/mediagoblin/plugins/basic_auth/forgot_password.html +++ /dev/null @@ -1,38 +0,0 @@ -{# -# GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 Free Software Foundation, Inc -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -#} -{% extends "mediagoblin/base.html" %} - -{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} - -{% block title -%} - {% trans %}Recover password{% endtrans %} — {{ super() }} -{%- endblock %} - -{% block mediagoblin_content %} -
- {{ csrf_token }} -
-

{% trans %}Recover password{% endtrans %}

- {{ wtforms_util.render_divs(fp_form) }} -
- -
-
-
-{% endblock %} diff --git a/mediagoblin/plugins/basic_auth/views.py b/mediagoblin/plugins/basic_auth/views.py deleted file mode 100644 index 69d2c52a..00000000 --- a/mediagoblin/plugins/basic_auth/views.py +++ /dev/null @@ -1,165 +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 . -import uuid -import datetime - -import forms as auth_forms -from mediagoblin.tools.response import render_to_response, redirect, render_404 -from mediagoblin.db.models import User -from mediagoblin.tools.translate import pass_to_ugettext as _ -from mediagoblin import messages -from mediagoblin.auth.views import email_debug_message -from mediagoblin.auth.lib import send_fp_verification_email -from mediagoblin.auth import lib as auth_lib - - - -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/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 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/plugins/basic_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/templates/mediagoblin/auth/forgot_password.html b/mediagoblin/templates/mediagoblin/auth/forgot_password.html index 6a74e2a2..a6c9e1e9 100644 --- a/mediagoblin/templates/mediagoblin/auth/forgot_password.html +++ b/mediagoblin/templates/mediagoblin/auth/forgot_password.html @@ -24,7 +24,7 @@ {%- endblock %} {% block mediagoblin_content %} -
{{ csrf_token }}
diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html index 6ec5d343..2adbe547 100644 --- a/mediagoblin/templates/mediagoblin/auth/login.html +++ b/mediagoblin/templates/mediagoblin/auth/login.html @@ -46,10 +46,12 @@

{% endif %} {{ wtforms_util.render_divs(login_form) }} + {% if pass_auth %}

{% trans %}Forgot your password?{% endtrans %}

+ {% endif %}
diff --git a/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini b/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini deleted file mode 100644 index b8c246f4..00000000 --- a/mediagoblin/tests/auth_configs/basic_auth_appconfig.ini +++ /dev/null @@ -1,28 +0,0 @@ -[mediagoblin] -direct_remote_path = /test_static/ -email_sender_address = "notice@mediagoblin.example.org" -email_debug_mode = true -no_auth = false - -# 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.basic_auth]] - diff --git a/mediagoblin/tests/basic_auth_appconfig.ini b/mediagoblin/tests/basic_auth_appconfig.ini deleted file mode 100644 index b15ae1fb..00000000 --- a/mediagoblin/tests/basic_auth_appconfig.ini +++ /dev/null @@ -1,28 +0,0 @@ -[mediagoblin] -direct_remote_path = /test_static/ -email_sender_address = "notice@mediagoblin.example.org" -email_debug_mode = true -no_auth = false - -# TODO: Switch to using an in-memory database -sql_engine = "sqlite:///%(here)s/test_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/test_user_dev/media/public -base_url = /mgoblin_media/ - -[storage:queuestore] -base_dir = %(here)s/test_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" - -[plugins] -[[mediagoblin.plugins.basic_auth]] - diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index c67d523f..ee916c43 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -13,9 +13,10 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import urlparse +import datetime import pkg_resources import pytest -import urlparse from mediagoblin import mg_globals from mediagoblin.db.models import User @@ -172,6 +173,86 @@ def test_register_views(test_app): ## TODO: Also check for double instances of an email address? + ### Oops, forgot the password + # ------------------- + template.clear_test_template_context() + response = test_app.post( + '/auth/forgot_password/', + {'username': u'happygirl'}) + response.follow() + + ## Did we redirect to the proper page? Use the right template? + assert urlparse.urlsplit(response.location)[2] == '/auth/login/' + assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT + + ## 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' + email_context = template.TEMPLATE_TEST_CONTEXT[ + 'mediagoblin/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 + + ## 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" + + ## 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() + + ## 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 + + ## 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', + 'token': parsed_get_params['token']}) + response.follow() + assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT + + ## Verify step 2.2 of password-change works -- login w/ new password success + template.clear_test_template_context() + response = test_app.post( + '/auth/login/', { + 'username': u'happygirl', + 'password': 'iamveryveryhappy'}) + + # User should be redirected + response.follow() + assert urlparse.urlsplit(response.location)[2] == '/' + assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT + def test_authentication_views(test_app): """ @@ -325,3 +406,12 @@ def test_no_auth_true_no_auth_plugin_app(no_auth_true_no_auth_plugin_app): ## Test check_login should return False assert auth.check_login('test', 'simple') is False + + # Try to visit the forgot password page + template.clear_test_template_context() + response = no_auth_true_no_auth_plugin_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 index a985c315..1b76aa3f 100644 --- a/mediagoblin/tests/test_basic_auth.py +++ b/mediagoblin/tests/test_basic_auth.py @@ -13,15 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import urlparse -import datetime -import pkg_resources -import pytest - from mediagoblin.plugins.basic_auth import lib as auth_lib -from mediagoblin import mg_globals -from mediagoblin.tools import template, mail -from mediagoblin.tests.tools import get_app, fixture_add_user from mediagoblin.tools.testing import _activate_testing _activate_testing() @@ -65,102 +57,3 @@ def test_bcrypt_gen_password_hash(): pw, hashed_pw, '3><7R45417') assert not auth_lib.bcrypt_check_password( 'notthepassword', hashed_pw, '3><7R45417') - - -@pytest.fixture() -def context_modified_app(request): - return get_app( - request, - mgoblin_config=pkg_resources.resource_filename( - 'mediagoblin.tests.auth_configs', 'basic_auth_appconfig.ini')) - - -def test_fp_view(context_modified_app): - ### Oops, forgot the password - ## Register a user - fixture_add_user(active_user=True) - - # ------------------- - template.clear_test_template_context() - response = context_modified_app.post( - '/auth/forgot_password/', - {'username': u'chris'}) - response.follow() - - ## Did we redirect to the proper page? Use the right template? - assert urlparse.urlsplit(response.location)[2] == '/auth/login/' - assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT - - ## 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'] == 'chris@example.com' - email_context = template.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/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'chris'}) - 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 - - ## Try using a bs password-changing verification key, shouldn't work - template.clear_test_template_context() - response = context_modified_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" - - ## 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'chris'}) - real_token_expiration = new_user.fp_token_expire - new_user.fp_token_expire = datetime.datetime.now() - new_user.save() - response = context_modified_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() - - ## Verify step 1 of password-change works -- can see form to - ## change password - template.clear_test_template_context() - response = context_modified_app.get("%s?%s" % (path, get_params)) - 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 = context_modified_app.post( - '/auth/forgot_password/verify/', { - 'userid': parsed_get_params['userid'], - 'password': 'iamveryveryhappy', - 'token': parsed_get_params['token']}) - response.follow() - assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT - - ## Verify step 2.2 of password-change works -- login w/ new password - ## success - template.clear_test_template_context() - response = context_modified_app.post( - '/auth/login/', { - 'username': u'chris', - 'password': 'iamveryveryhappy'}) - - # User should be redirected - response.follow() - assert urlparse.urlsplit(response.location)[2] == '/' - assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT From 89e1563f683c620387c782c363d63f90abd46a33 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 21 May 2013 16:21:33 -0700 Subject: [PATCH 032/153] added support for user to change email address --- mediagoblin/auth/lib.py | 25 +++-- mediagoblin/edit/forms.py | 14 ++- mediagoblin/edit/routing.py | 2 + mediagoblin/edit/views.py | 105 +++++++++++++++--- .../mediagoblin/edit/edit_account.html | 2 + .../mediagoblin/edit/verification.txt | 29 +++++ 6 files changed, 150 insertions(+), 27 deletions(-) create mode 100644 mediagoblin/templates/mediagoblin/edit/verification.txt diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 8829995a..8bba8484 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -95,7 +95,8 @@ EMAIL_VERIFICATION_TEMPLATE = ( u"userid={userid}&token={verification_key}") -def send_verification_email(user, request): +def send_verification_email(user, request, email=None, + rendered_email=None): """ Send the verification email to users to activate their accounts. @@ -103,19 +104,23 @@ def send_verification_email(user, request): - 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)}) + if not email: + email = user.email + + if not rendered_email: + 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], + [email], # TODO # Due to the distributed nature of GNU MediaGoblin, we should # find a way to send some additional information about the diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py index 3b2486de..3a502263 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.forms import normalize_user_or_email_field + class EditForm(wtforms.Form): title = wtforms.TextField( @@ -59,6 +61,16 @@ class EditProfileForm(wtforms.Form): class EditAccountForm(wtforms.Form): + new_email = wtforms.TextField( + _('New email address'), + [wtforms.validators.Optional(), + normalize_user_or_email_field(allow_user=False)]) + password = wtforms.PasswordField( + _('Password'), + [wtforms.validators.Optional(), + wtforms.validators.Length(min=5, max=1024)], + description=_( + 'Enter your old password to prove you own this account.')) license_preference = wtforms.SelectField( _('License preference'), [ diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py index 622729ac..67c2c7be 100644 --- a/mediagoblin/edit/routing.py +++ b/mediagoblin/edit/routing.py @@ -26,3 +26,5 @@ add_route('mediagoblin.edit.delete_account', '/edit/account/delete/', 'mediagoblin.edit.views:delete_account') add_route('mediagoblin.edit.pass', '/edit/password/', 'mediagoblin.edit.views:change_pass') +add_route('mediagoblin.edit.verify_email', '/edit/verify_email', + 'mediagoblin.edit.views:verify_email') diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 508c380d..78e47fe0 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -23,18 +23,22 @@ from mediagoblin import messages from mediagoblin import mg_globals from mediagoblin.auth import lib as auth_lib +from mediagoblin.auth.views import email_debug_message 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, redirect_obj + get_media_entry_by_id, user_may_alter_collection, + get_user_collection) +from mediagoblin.tools.crypto import get_timed_signer_url +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 @@ -212,6 +216,10 @@ 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): @@ -220,27 +228,57 @@ def edit_account(request): wants_comment_notification=user.wants_comment_notification, license_preference=user.license_preference) - if request.method == 'POST': - form_validated = form.validate() - - if form_validated and \ - form.wants_comment_notification.validate(form): + if request.method == 'POST' and form.validate(): + if form.wants_comment_notification.validate(form): user.wants_comment_notification = \ form.wants_comment_notification.data - if form_validated and \ - form.license_preference.validate(form): + if form.license_preference.validate(form): user.license_preference = \ form.license_preference.data - if form_validated and not form.errors: + if form.new_email.data: + if not form.password.data: + form.password.errors.append( + _('This field is required.')) + elif not auth_lib.bcrypt_check_password( + form.password.data, user.pw_hash): + form.password.errors.append( + _('Wrong password.')) + else: + 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.')) + else: + 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_lib.send_verification_email(user, request, new_email, + rendered_email) + + if not form.errors: user.save() messages.add_message(request, - messages.SUCCESS, - _("Account settings saved")) + messages.SUCCESS, + _("Account settings saved")) return redirect(request, - 'mediagoblin.user_pages.user_home', - user=user.username) + 'mediagoblin.user_pages.user_home', + user=user.username) return render_to_response( request, @@ -369,3 +407,38 @@ def change_pass(request): 'mediagoblin/edit/change_pass.html', {'form': form, 'user': user}) + + +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) + + # This throws an error, if the thing is faked or expired + # should be catched, probably. + token = get_timed_signer_url("mail_verification_token") \ + .loads(request.GET['token'], max_age=10*24*3600) + + 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) diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html index 4c4aaf95..d56b3ba0 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_account.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html @@ -46,6 +46,8 @@ {% trans %}Change your password.{% endtrans %}

+ {{ wtforms_util.render_field_div(form.new_email) }} + {{ wtforms_util.render_field_div(form.password) }}

{{ form.wants_comment_notification }} {{ wtforms_util.render_label(form.wants_comment_notification) }}

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 . +-#} + +{% 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 %} From 377db0e7ffdca6ce56041d28eba536ecd3b2a58a Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 21 May 2013 17:25:00 -0700 Subject: [PATCH 033/153] added error handling on bad token, fixed route, and added tests --- mediagoblin/edit/routing.py | 2 +- mediagoblin/edit/views.py | 19 ++++-- mediagoblin/tests/test_edit.py | 106 ++++++++++++++++++++++++++++++++- 3 files changed, 120 insertions(+), 7 deletions(-) diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py index 67c2c7be..3592f708 100644 --- a/mediagoblin/edit/routing.py +++ b/mediagoblin/edit/routing.py @@ -26,5 +26,5 @@ add_route('mediagoblin.edit.delete_account', '/edit/account/delete/', 'mediagoblin.edit.views:delete_account') add_route('mediagoblin.edit.pass', '/edit/password/', 'mediagoblin.edit.views:change_pass') -add_route('mediagoblin.edit.verify_email', '/edit/verify_email', +add_route('mediagoblin.edit.verify_email', '/edit/verify_email/', 'mediagoblin.edit.views:verify_email') diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 78e47fe0..249fb8ba 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -16,6 +16,7 @@ from datetime import datetime +from itsdangerous import BadSignature from werkzeug.exceptions import Forbidden from werkzeug.utils import secure_filename @@ -417,10 +418,20 @@ def verify_email(request): if not 'token' in request.GET: return render_404(request) - # This throws an error, if the thing is faked or expired - # should be catched, probably. - token = get_timed_signer_url("mail_verification_token") \ - .loads(request.GET['token'], max_age=10*24*3600) + # 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() diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py index 08b4f8cf..76fd5ee9 100644 --- a/mediagoblin/tests/test_edit.py +++ b/mediagoblin/tests/test_edit.py @@ -15,14 +15,14 @@ # along with this program. If not, see . import urlparse -import pytest 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.tools import template, mail from mediagoblin.auth.lib import bcrypt_check_password + class TestUserEdit(object): def setup(self): # set up new user @@ -141,4 +141,106 @@ 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 change without password + template.clear_test_template_context() + test_app.post( + '/edit/account/', { + 'new_email': 'new@example.com'}) + + # Check form errors + context = template.TEMPLATE_TEST_CONTEXT[ + 'mediagoblin/edit/edit_account.html'] + assert context['form'].password.errors == [ + u'This field is required.'] + + # Test email change with wrong password + template.clear_test_template_context() + test_app.post( + '/edit/account/', { + 'new_email': 'new@example.com', + 'password': 'wrong'}) + + # Check form errors + context = template.TEMPLATE_TEST_CONTEXT[ + 'mediagoblin/edit/edit_account.html'] + assert context['form'].password.errors == [ + u'Wrong password.'] + + # Test email already in db + template.clear_test_template_context() + test_app.post( + '/edit/account/', { + 'new_email': 'chris@example.com', + 'password': 'toast'}) + + # Check form errors + context = template.TEMPLATE_TEST_CONTEXT[ + 'mediagoblin/edit/edit_account.html'] + assert context['form'].new_email.errors == [ + u'Sorry, a user with that email address already exists.'] + + # Test password is too short + template.clear_test_template_context() + test_app.post( + '/edit/account/', { + 'new_email': 'new@example.com', + 'password': 't'}) + + # Check form errors + context = template.TEMPLATE_TEST_CONTEXT[ + 'mediagoblin/edit/edit_account.html'] + assert context['form'].password.errors == [ + u'Field must be between 5 and 1024 characters long.'] + + # Test successful email change + template.clear_test_template_context() + res = test_app.post( + '/edit/account/', { + 'new_email': 'new@example.com', + 'password': 'toast'}) + res.follow() + + # Correct redirect? + assert urlparse.urlsplit(res.location)[2] == '/u/chris/' + + # 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.find_one( + {'email': 'new@example.com'}) + 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 From 8ad734afc677f2d8314981be08d9282d5d599c67 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 14:33:56 -0700 Subject: [PATCH 034/153] changed User model pw_hash field to nullable and added migrations --- mediagoblin/db/migrations.py | 11 +++++++++++ mediagoblin/db/models.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 2c553396..1f92417e 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -287,3 +287,14 @@ def unique_collections_slug(db): constraint.create() db.commit() + + +@RegisterMigration(11, 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) + + db.commit() diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 2b925983..323ed4d7 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -61,7 +61,7 @@ class User(Base, UserMixin): # point. email = Column(Unicode, nullable=False) created = Column(DateTime, nullable=False, default=datetime.datetime.now) - pw_hash = Column(Unicode, nullable=False) + pw_hash = Column(Unicode) 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 From 61bfe64b23ab7c99653f0359e3344cf7c5d161f7 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 14:56:32 -0700 Subject: [PATCH 035/153] removed unused import --- mediagoblin/auth/forms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 599b2576..0a391d67 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -16,7 +16,6 @@ import wtforms -from mediagoblin.tools.mail import normalize_email from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.auth.tools import normalize_user_or_email_field From 92783bc1fd41efa228639703127523469614e9aa Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 12:26:45 -0700 Subject: [PATCH 036/153] moved send_verification_email to auth/tools --- mediagoblin/auth/lib.py | 35 ----------------------------------- mediagoblin/auth/tools.py | 39 ++++++++++++++++++++++++++++++++++++++- mediagoblin/auth/views.py | 6 +++--- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 8829995a..bfc36b28 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -90,41 +90,6 @@ 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}") diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 1b30a7d9..52095d8a 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -16,7 +16,9 @@ import wtforms -from mediagoblin.tools.mail import normalize_email +from mediagoblin import mg_globals +from mediagoblin.tools.mail import normalize_email, send_email +from mediagoblin.tools.template import render_template from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ @@ -48,3 +50,38 @@ def normalize_user_or_email_field(allow_email=True, allow_user=True): if field.data is None: # should not happen, but be cautious anyway raise wtforms.ValidationError(message) return _normalize_field + + +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) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dc408911..94354933 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -23,8 +23,8 @@ 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 mediagoblin.auth.lib import send_fp_verification_email +from mediagoblin.auth.tools import send_verification_email from sqlalchemy import or_ def email_debug_message(request): @@ -113,7 +113,7 @@ def login(request): login_failed = False if request.method == 'POST': - + username = login_form.data['username'] if login_form.validate(): From dd39fe6052ff41a2f64467e1019479c093bfe4da Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 12:48:29 -0700 Subject: [PATCH 037/153] moved email_debug_message to gmg/tools/mail --- mediagoblin/auth/views.py | 13 +------------ mediagoblin/tools/mail.py | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 94354933..6a8e9a4c 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -21,24 +21,13 @@ from mediagoblin import messages, mg_globals from mediagoblin.db.models import User from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.mail import email_debug_message from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_fp_verification_email from mediagoblin.auth.tools import send_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.") - def register(request): """The registration view. diff --git a/mediagoblin/tools/mail.py b/mediagoblin/tools/mail.py index 4fa02ce5..6886c859 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 ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -135,3 +135,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.") From 310a44d57c121405a6279ad0eae2ed1f07f82b56 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 12:52:14 -0700 Subject: [PATCH 038/153] added a register_user function --- mediagoblin/auth/tools.py | 53 ++++++++++++++++++++++++++++++++++++++- mediagoblin/auth/views.py | 35 +++----------------------- 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 52095d8a..16611757 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -14,10 +14,14 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import uuid import wtforms from mediagoblin import mg_globals -from mediagoblin.tools.mail import normalize_email, send_email +from mediagoblin.auth import lib as auth_lib +from mediagoblin.db.models import User +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 _ @@ -85,3 +89,50 @@ def send_verification_email(user, request): # 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.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 + + return extra_validation_passes + + +def register_user(request, register_form): + """ Handle user registration """ + extra_validation_passes = basic_extra_validation(register_form) + + 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) + + return user + + return None diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 6a8e9a4c..574adab5 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -25,7 +25,7 @@ from mediagoblin.tools.mail import email_debug_message from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_fp_verification_email -from mediagoblin.auth.tools import send_verification_email +from mediagoblin.auth.tools import send_verification_email, register_user from sqlalchemy import or_ @@ -47,38 +47,9 @@ def register(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( From 1d321f1c7158f3bd263d64ae703311e8d8e2a22a Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Sat, 25 May 2013 07:59:03 -0700 Subject: [PATCH 039/153] created a check_login_simple function --- mediagoblin/auth/tools.py | 21 +++++++++++++++++++++ mediagoblin/auth/views.py | 17 ++++------------- mediagoblin/db/mixin.py | 8 -------- mediagoblin/plugins/httpapiauth/__init__.py | 7 ++++--- mediagoblin/plugins/piwigo/views.py | 12 +++--------- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 16611757..db6b6e37 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -15,7 +15,10 @@ # along with this program. If not, see . import uuid +import logging + import wtforms +from sqlalchemy import or_ from mediagoblin import mg_globals from mediagoblin.auth import lib as auth_lib @@ -25,6 +28,8 @@ from mediagoblin.tools.mail import (normalize_email, send_email, from mediagoblin.tools.template import render_template from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +_log = logging.getLogger(__name__) + def normalize_user_or_email_field(allow_email=True, allow_user=True): """ @@ -136,3 +141,19 @@ def register_user(request, register_form): return user return None + + +def check_login_simple(username, password, username_might_be_email=False): + search = (User.username == username) + if username_might_be_email and ('@' in username): + search = or_(search, User.email == username) + user = User.query.filter(search).first() + if not user: + _log.info("User %r not found", username) + auth_lib.fake_login_attempt() + return None + if not auth_lib.bcrypt_check_password(password, user.pw_hash): + _log.warn("Wrong password for %r", username) + return None + _log.info("Logging %r in", username) + return user diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 574adab5..bb7bda77 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -25,8 +25,8 @@ from mediagoblin.tools.mail import email_debug_message from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_fp_verification_email -from mediagoblin.auth.tools import send_verification_email, register_user -from sqlalchemy import or_ +from mediagoblin.auth.tools import (send_verification_email, register_user, + check_login_simple) def register(request): @@ -77,14 +77,9 @@ def login(request): username = login_form.data['username'] if login_form.validate(): - user = User.query.filter( - or_( - User.username == username, - User.email == username, + user = check_login_simple(username, login_form.password.data, True) - )).first() - - if user and user.check_login(login_form.password.data): + if user: # set up login in session request.session['user_id'] = unicode(user.id) request.session.save() @@ -94,10 +89,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( diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index e7f66fa1..9f566e36 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -34,7 +34,6 @@ 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.tools import common, licenses from mediagoblin.tools.text import cleaned_markdown_conversion @@ -42,13 +41,6 @@ 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) diff --git a/mediagoblin/plugins/httpapiauth/__init__.py b/mediagoblin/plugins/httpapiauth/__init__.py index 99b6a4b0..2b2d593c 100644 --- a/mediagoblin/plugins/httpapiauth/__init__.py +++ b/mediagoblin/plugins/httpapiauth/__init__.py @@ -18,6 +18,7 @@ import logging from werkzeug.exceptions import Unauthorized +from mediagoblin.auth.tools import check_login_simple from mediagoblin.plugins.api.tools import Auth _log = logging.getLogger(__name__) @@ -39,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/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index 78668ed4..ca723189 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -23,7 +23,7 @@ from werkzeug.exceptions import MethodNotAllowed, BadRequest, NotImplemented from werkzeug.wrappers import BaseResponse from mediagoblin.meddleware.csrf import csrf_exempt -from mediagoblin.auth.lib import fake_login_attempt +from mediagoblin.auth.tools import check_login_simple from mediagoblin.media_types import sniff_media from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \ run_process_media, new_upload_entry @@ -43,15 +43,9 @@ _log = logging.getLogger(__name__) def pwg_login(request): username = request.form.get("username") password = request.form.get("password") - user = request.db.User.query.filter_by(username=username).first() + user = check_login_simple(username, password) if not user: - _log.info("User %r not found", username) - fake_login_attempt() return PwgError(999, 'Invalid username/password') - if not user.check_login(password): - _log.warn("Wrong password for %r", username) - return PwgError(999, 'Invalid username/password') - _log.info("Logging %r in", username) request.session["user_id"] = user.id request.session.save() return True @@ -126,7 +120,7 @@ def pwg_images_addSimple(request): dump = [] for f in form: dump.append("%s=%r" % (f.name, f.data)) - _log.info("addSimple: %r %s %r", request.form, " ".join(dump), + _log.info("addSimple: %r %s %r", request.form, " ".join(dump), request.files) if not check_file_field(request, 'image'): From cdc6b571e33ee0cd90fa8f2be270df77d7f6d9d9 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 27 May 2013 08:39:34 -0700 Subject: [PATCH 040/153] cleanup after merge --- mediagoblin/auth/__init__.py | 4 ++-- mediagoblin/auth/tools.py | 9 +++------ mediagoblin/auth/views.py | 3 +-- mediagoblin/plugins/basic_auth/__init__.py | 18 ++++++++---------- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index 53182eaa..ae6c4b96 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -23,8 +23,8 @@ def check_login(user, password): return False -def get_user(form): - return hook_handle("auth_get_user", form) +def get_user(username): + return hook_handle("auth_get_user", username) def create_user(register_form): diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index f38a292a..94a9781b 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -199,15 +199,12 @@ def send_fp_verification_email(user, request): def check_login_simple(username, password, username_might_be_email=False): - search = (User.username == username) - if username_might_be_email and ('@' in username): - search = or_(search, User.email == username) - user = User.query.filter(search).first() + user = auth.get_user(username) if not user: _log.info("User %r not found", username) - auth_lib.fake_login_attempt() + auth.fake_login_attempt() return None - if not auth_lib.bcrypt_check_password(password, user.pw_hash): + if not auth.check_password(password, user.pw_hash): _log.warn("Wrong password for %r", username) return None _log.info("Logging %r in", username) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 109763ce..b62602b3 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -22,7 +22,6 @@ from mediagoblin.db.models import User from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools.mail import email_debug_message -from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.tools import (send_verification_email, register_user, @@ -301,7 +300,7 @@ def verify_forgot_password(request): cp_form = auth_forms.ChangePassForm(formdata_vars) if request.method == 'POST' and cp_form.validate(): - user.pw_hash = auth_lib.bcrypt_gen_password_hash( + user.pw_hash = auth.gen_password_hash( cp_form.password.data) user.fp_verification_key = None user.fp_token_expire = None diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 2fe161cb..edbfacb5 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -34,19 +34,17 @@ def check_login(user, password): return None -def get_user(form): - if 'username' in form.data: - username = form.username.data - user = User.query.filter( - or_( - User.username == username, - User.email == username, - )).first() - return user +def get_user(username): + user = User.query.filter( + or_( + User.username == username, + User.email == username, + )).first() + return user def create_user(registration_form): - user = get_user(registration_form) + user = get_user(registration_form.username.data) if not user and 'password' in registration_form: user = User() user.username = registration_form.username.data From 3bcdc49088a9fe779b1b95fb1dc42d9ef0c4de00 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 27 May 2013 08:43:12 -0700 Subject: [PATCH 041/153] renamed lib to tools --- mediagoblin/auth/tools.py | 1 - mediagoblin/plugins/basic_auth/__init__.py | 12 +++++------ .../plugins/basic_auth/{lib.py => tools.py} | 0 mediagoblin/tests/test_basic_auth.py | 20 +++++++++---------- 4 files changed, 16 insertions(+), 17 deletions(-) rename mediagoblin/plugins/basic_auth/{lib.py => tools.py} (100%) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 94a9781b..db1a6297 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -20,7 +20,6 @@ import wtforms from sqlalchemy import or_ from mediagoblin import mg_globals -from mediagoblin.auth import lib as auth_lib from mediagoblin.db.models import User from mediagoblin.tools.mail import (normalize_email, send_email, email_debug_message) diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index edbfacb5..fe314504 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -16,7 +16,7 @@ import uuid from mediagoblin.plugins.basic_auth import forms as auth_forms -from mediagoblin.plugins.basic_auth import lib as auth_lib +from mediagoblin.plugins.basic_auth import tools as auth_tools from mediagoblin.db.models import User from mediagoblin.tools import pluginapi from sqlalchemy import or_ @@ -28,7 +28,7 @@ def setup_plugin(): def check_login(user, password): if user.pw_hash: - result = auth_lib.bcrypt_check_password(password, user.pw_hash) + result = check_password(password, user.pw_hash) if result: return result return None @@ -49,7 +49,7 @@ def create_user(registration_form): user = User() user.username = registration_form.username.data user.email = registration_form.email.data - user.pw_hash = auth_lib.bcrypt_gen_password_hash( + user.pw_hash = igen_password_hash( registration_form.password.data) user.verification_key = unicode(uuid.uuid4()) user.save() @@ -65,11 +65,11 @@ def get_registration_form(request): def gen_password_hash(raw_pass, extra_salt): - return auth_lib.bcrypt_gen_password_hash(raw_pass, extra_salt) + return auth_tools.bcrypt_gen_password_hash(raw_pass, extra_salt) def check_password(raw_pass, stored_hash, extra_salt): - return auth_lib.bcrypt_check_password(raw_pass, stored_hash, extra_salt) + return auth_tools.bcrypt_check_password(raw_pass, stored_hash, extra_salt) def auth(): @@ -96,7 +96,7 @@ hooks = { 'auth_get_registration_form': get_registration_form, 'auth_gen_password_hash': gen_password_hash, 'auth_check_password': check_password, - 'auth_fake_login_attempt': auth_lib.fake_login_attempt, + 'auth_fake_login_attempt': auth_tools.fake_login_attempt, 'template_global_context': append_to_global_context, ('mediagoblin.plugins.openid.register', 'mediagoblin/auth/register.html'): add_to_form_context, diff --git a/mediagoblin/plugins/basic_auth/lib.py b/mediagoblin/plugins/basic_auth/tools.py similarity index 100% rename from mediagoblin/plugins/basic_auth/lib.py rename to mediagoblin/plugins/basic_auth/tools.py diff --git a/mediagoblin/tests/test_basic_auth.py b/mediagoblin/tests/test_basic_auth.py index 1b76aa3f..cdd80fca 100644 --- a/mediagoblin/tests/test_basic_auth.py +++ b/mediagoblin/tests/test_basic_auth.py @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from mediagoblin.plugins.basic_auth import lib as auth_lib +from mediagoblin.plugins.basic_auth import tools as auth_tools from mediagoblin.tools.testing import _activate_testing _activate_testing() @@ -26,16 +26,16 @@ _activate_testing() def test_bcrypt_check_password(): # Check known 'lollerskates' password against check function - assert auth_lib.bcrypt_check_password( + assert auth_tools.bcrypt_check_password( 'lollerskates', '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO') - assert not auth_lib.bcrypt_check_password( + assert not auth_tools.bcrypt_check_password( 'notthepassword', '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO') # Same thing, but with extra fake salt. - assert not auth_lib.bcrypt_check_password( + assert not auth_tools.bcrypt_check_password( 'notthepassword', '$2a$12$ELVlnw3z1FMu6CEGs/L8XO8vl0BuWSlUHgh0rUrry9DUXGMUNWwl6', '3><7R45417') @@ -45,15 +45,15 @@ 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( + hashed_pw = auth_tools.bcrypt_gen_password_hash(pw) + assert auth_tools.bcrypt_check_password( pw, hashed_pw) - assert not auth_lib.bcrypt_check_password( + assert not auth_tools.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( + 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_lib.bcrypt_check_password( + assert not auth_tools.bcrypt_check_password( 'notthepassword', hashed_pw, '3><7R45417') From 3b8c733b98533e6dd7612f071b672b19a97ecf1e Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 27 May 2013 08:54:25 -0700 Subject: [PATCH 042/153] no need for check_login with the new check_login_simple function --- mediagoblin/auth/__init__.py | 7 ------- mediagoblin/auth/tools.py | 1 - mediagoblin/plugins/basic_auth/__init__.py | 15 +++------------ mediagoblin/tests/test_auth.py | 5 +++-- 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index ae6c4b96..8cb1f401 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -16,13 +16,6 @@ from mediagoblin.tools.pluginapi import hook_handle, hook_runall -def check_login(user, password): - result = hook_handle("auth_check_login", user, password) - if result: - return result - return False - - def get_user(username): return hook_handle("auth_get_user", username) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index db1a6297..484c3030 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -17,7 +17,6 @@ import logging import wtforms -from sqlalchemy import or_ from mediagoblin import mg_globals from mediagoblin.db.models import User diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index fe314504..375af335 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -26,14 +26,6 @@ def setup_plugin(): config = pluginapi.get_config('mediagoblin.pluginapi.basic_auth') -def check_login(user, password): - if user.pw_hash: - result = check_password(password, user.pw_hash) - if result: - return result - return None - - def get_user(username): user = User.query.filter( or_( @@ -49,7 +41,7 @@ def create_user(registration_form): user = User() user.username = registration_form.username.data user.email = registration_form.email.data - user.pw_hash = igen_password_hash( + user.pw_hash = gen_password_hash( registration_form.password.data) user.verification_key = unicode(uuid.uuid4()) user.save() @@ -64,11 +56,11 @@ def get_registration_form(request): return auth_forms.RegistrationForm(request.form) -def gen_password_hash(raw_pass, extra_salt): +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): +def check_password(raw_pass, stored_hash, extra_salt=None): return auth_tools.bcrypt_check_password(raw_pass, stored_hash, extra_salt) @@ -89,7 +81,6 @@ def add_to_form_context(context): hooks = { 'setup': setup_plugin, 'authentication': auth, - 'auth_check_login': check_login, 'auth_get_user': get_user, 'auth_create_user': create_user, 'auth_get_login_form': get_login_form, diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index ee916c43..8a828303 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -23,6 +23,7 @@ from mediagoblin.db.models import User from mediagoblin.tests.tools import get_app, fixture_add_user from mediagoblin.tools import template, mail from mediagoblin.auth.tools import AuthError +from mediagoblin.auth import tools as auth_tools from mediagoblin import auth @@ -404,8 +405,8 @@ def test_no_auth_true_no_auth_plugin_app(no_auth_true_no_auth_plugin_app): assert urlparse.urlsplit(response.location)[2] == '/' assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT - ## Test check_login should return False - assert auth.check_login('test', 'simple') is False + ## 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() From 53012d08c59e36acfb51576368bc4595ab701edc Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 14:33:56 -0700 Subject: [PATCH 043/153] changed User model pw_hash field to nullable and added migrations --- mediagoblin/db/migrations.py | 11 +++++++++++ mediagoblin/db/models.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 2c553396..1f92417e 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -287,3 +287,14 @@ def unique_collections_slug(db): constraint.create() db.commit() + + +@RegisterMigration(11, 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) + + db.commit() diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 2b925983..323ed4d7 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -61,7 +61,7 @@ class User(Base, UserMixin): # point. email = Column(Unicode, nullable=False) created = Column(DateTime, nullable=False, default=datetime.datetime.now) - pw_hash = Column(Unicode, nullable=False) + pw_hash = Column(Unicode) 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 From d7d5ce803d1fec7c0dcd6aac81c58ed53199075f Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 23 May 2013 14:56:32 -0700 Subject: [PATCH 044/153] removed unused import --- mediagoblin/auth/forms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 599b2576..0a391d67 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -16,7 +16,6 @@ import wtforms -from mediagoblin.tools.mail import normalize_email from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.auth.tools import normalize_user_or_email_field From c6e46c6bd9c616a500ae9395178a2ab57f25baa8 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 12:26:45 -0700 Subject: [PATCH 045/153] moved send_verification_email to auth/tools --- mediagoblin/auth/lib.py | 35 ----------------------------------- mediagoblin/auth/tools.py | 39 ++++++++++++++++++++++++++++++++++++++- mediagoblin/auth/views.py | 6 +++--- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 8829995a..bfc36b28 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -90,41 +90,6 @@ 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}") diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 1b30a7d9..52095d8a 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -16,7 +16,9 @@ import wtforms -from mediagoblin.tools.mail import normalize_email +from mediagoblin import mg_globals +from mediagoblin.tools.mail import normalize_email, send_email +from mediagoblin.tools.template import render_template from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ @@ -48,3 +50,38 @@ def normalize_user_or_email_field(allow_email=True, allow_user=True): if field.data is None: # should not happen, but be cautious anyway raise wtforms.ValidationError(message) return _normalize_field + + +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) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index dc408911..94354933 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -23,8 +23,8 @@ 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 mediagoblin.auth.lib import send_fp_verification_email +from mediagoblin.auth.tools import send_verification_email from sqlalchemy import or_ def email_debug_message(request): @@ -113,7 +113,7 @@ def login(request): login_failed = False if request.method == 'POST': - + username = login_form.data['username'] if login_form.validate(): From 81907fa0aac7757d1c39cafef4da89f8b2bfb417 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 12:48:29 -0700 Subject: [PATCH 046/153] moved email_debug_message to gmg/tools/mail --- mediagoblin/auth/views.py | 13 +------------ mediagoblin/tools/mail.py | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 94354933..6a8e9a4c 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -21,24 +21,13 @@ from mediagoblin import messages, mg_globals from mediagoblin.db.models import User from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.tools.mail import email_debug_message from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_fp_verification_email from mediagoblin.auth.tools import send_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.") - def register(request): """The registration view. diff --git a/mediagoblin/tools/mail.py b/mediagoblin/tools/mail.py index 4fa02ce5..6886c859 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 ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -135,3 +135,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.") From 68cc79eb4adf8046bc2a6c00d97af4fb637440f6 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 24 May 2013 12:52:14 -0700 Subject: [PATCH 047/153] added a register_user function --- mediagoblin/auth/tools.py | 53 ++++++++++++++++++++++++++++++++++++++- mediagoblin/auth/views.py | 35 +++----------------------- 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 52095d8a..16611757 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -14,10 +14,14 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import uuid import wtforms from mediagoblin import mg_globals -from mediagoblin.tools.mail import normalize_email, send_email +from mediagoblin.auth import lib as auth_lib +from mediagoblin.db.models import User +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 _ @@ -85,3 +89,50 @@ def send_verification_email(user, request): # 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.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 + + return extra_validation_passes + + +def register_user(request, register_form): + """ Handle user registration """ + extra_validation_passes = basic_extra_validation(register_form) + + 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) + + return user + + return None diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 6a8e9a4c..574adab5 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -25,7 +25,7 @@ from mediagoblin.tools.mail import email_debug_message from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_fp_verification_email -from mediagoblin.auth.tools import send_verification_email +from mediagoblin.auth.tools import send_verification_email, register_user from sqlalchemy import or_ @@ -47,38 +47,9 @@ def register(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( From 117a27a3aa03d22b1b1dac9379c7c179a29eb621 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Sat, 25 May 2013 07:59:03 -0700 Subject: [PATCH 048/153] created a check_login_simple function --- mediagoblin/auth/tools.py | 21 +++++++++++++++++++++ mediagoblin/auth/views.py | 17 ++++------------- mediagoblin/db/mixin.py | 8 -------- mediagoblin/plugins/httpapiauth/__init__.py | 7 ++++--- mediagoblin/plugins/piwigo/views.py | 12 +++--------- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 16611757..db6b6e37 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -15,7 +15,10 @@ # along with this program. If not, see . import uuid +import logging + import wtforms +from sqlalchemy import or_ from mediagoblin import mg_globals from mediagoblin.auth import lib as auth_lib @@ -25,6 +28,8 @@ from mediagoblin.tools.mail import (normalize_email, send_email, from mediagoblin.tools.template import render_template from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ +_log = logging.getLogger(__name__) + def normalize_user_or_email_field(allow_email=True, allow_user=True): """ @@ -136,3 +141,19 @@ def register_user(request, register_form): return user return None + + +def check_login_simple(username, password, username_might_be_email=False): + search = (User.username == username) + if username_might_be_email and ('@' in username): + search = or_(search, User.email == username) + user = User.query.filter(search).first() + if not user: + _log.info("User %r not found", username) + auth_lib.fake_login_attempt() + return None + if not auth_lib.bcrypt_check_password(password, user.pw_hash): + _log.warn("Wrong password for %r", username) + return None + _log.info("Logging %r in", username) + return user diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 574adab5..bb7bda77 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -25,8 +25,8 @@ from mediagoblin.tools.mail import email_debug_message from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.lib import send_fp_verification_email -from mediagoblin.auth.tools import send_verification_email, register_user -from sqlalchemy import or_ +from mediagoblin.auth.tools import (send_verification_email, register_user, + check_login_simple) def register(request): @@ -77,14 +77,9 @@ def login(request): username = login_form.data['username'] if login_form.validate(): - user = User.query.filter( - or_( - User.username == username, - User.email == username, + user = check_login_simple(username, login_form.password.data, True) - )).first() - - if user and user.check_login(login_form.password.data): + if user: # set up login in session request.session['user_id'] = unicode(user.id) request.session.save() @@ -94,10 +89,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( diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index e7f66fa1..9f566e36 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -34,7 +34,6 @@ 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.tools import common, licenses from mediagoblin.tools.text import cleaned_markdown_conversion @@ -42,13 +41,6 @@ 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) diff --git a/mediagoblin/plugins/httpapiauth/__init__.py b/mediagoblin/plugins/httpapiauth/__init__.py index 99b6a4b0..2b2d593c 100644 --- a/mediagoblin/plugins/httpapiauth/__init__.py +++ b/mediagoblin/plugins/httpapiauth/__init__.py @@ -18,6 +18,7 @@ import logging from werkzeug.exceptions import Unauthorized +from mediagoblin.auth.tools import check_login_simple from mediagoblin.plugins.api.tools import Auth _log = logging.getLogger(__name__) @@ -39,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/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py index 78668ed4..ca723189 100644 --- a/mediagoblin/plugins/piwigo/views.py +++ b/mediagoblin/plugins/piwigo/views.py @@ -23,7 +23,7 @@ from werkzeug.exceptions import MethodNotAllowed, BadRequest, NotImplemented from werkzeug.wrappers import BaseResponse from mediagoblin.meddleware.csrf import csrf_exempt -from mediagoblin.auth.lib import fake_login_attempt +from mediagoblin.auth.tools import check_login_simple from mediagoblin.media_types import sniff_media from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \ run_process_media, new_upload_entry @@ -43,15 +43,9 @@ _log = logging.getLogger(__name__) def pwg_login(request): username = request.form.get("username") password = request.form.get("password") - user = request.db.User.query.filter_by(username=username).first() + user = check_login_simple(username, password) if not user: - _log.info("User %r not found", username) - fake_login_attempt() return PwgError(999, 'Invalid username/password') - if not user.check_login(password): - _log.warn("Wrong password for %r", username) - return PwgError(999, 'Invalid username/password') - _log.info("Logging %r in", username) request.session["user_id"] = user.id request.session.save() return True @@ -126,7 +120,7 @@ def pwg_images_addSimple(request): dump = [] for f in form: dump.append("%s=%r" % (f.name, f.data)) - _log.info("addSimple: %r %s %r", request.form, " ".join(dump), + _log.info("addSimple: %r %s %r", request.form, " ".join(dump), request.files) if not check_file_field(request, 'image'): From f855efff87c22ddb6b2a7ad690933de02ddfbc62 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 27 May 2013 08:57:56 -0700 Subject: [PATCH 049/153] moved fp_verification_email to auth/tools --- mediagoblin/auth/lib.py | 34 ---------------------------------- mediagoblin/auth/tools.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index bfc36b28..47f9097f 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -18,10 +18,6 @@ import random import bcrypt -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): """ @@ -88,33 +84,3 @@ def fake_login_attempt(): randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt) randplus_stored_hash == randplus_hashed_pass - - -EMAIL_FP_VERIFICATION_TEMPLATE = ( - u"http://{host}{uri}?" - u"userid={userid}&token={fp_verification_key}") - - -def send_fp_verification_email(user, request): - """ - Send the verification email to users to change their password. - - Args: - - user: a user object - - request: the request - """ - rendered_email = render_template( - request, 'mediagoblin/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)}) - - # TODO: There is no error handling in place - send_email( - mg_globals.app_config['email_sender_address'], - [user.email], - 'GNU MediaGoblin - Change forgotten password!', - rendered_email) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index db6b6e37..b6c7d5c5 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -96,6 +96,36 @@ def send_verification_email(user, request): rendered_email) +EMAIL_FP_VERIFICATION_TEMPLATE = ( + u"http://{host}{uri}?" + u"userid={userid}&token={fp_verification_key}") + + +def send_fp_verification_email(user, request): + """ + Send the verification email to users to change their password. + + Args: + - user: a user object + - request: the request + """ + rendered_email = render_template( + request, 'mediagoblin/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)}) + + # TODO: There is no error handling in place + send_email( + mg_globals.app_config['email_sender_address'], + [user.email], + 'GNU MediaGoblin - Change forgotten password!', + rendered_email) + + def basic_extra_validation(register_form, *args): users_with_username = User.query.filter_by( username=register_form.data['username']).count() From f81206df311afbe0fdbc3eeb03a6cc601ee5ae2b Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 27 May 2013 10:38:09 -0700 Subject: [PATCH 050/153] no need for user might be email kwarg in check_login_simple --- mediagoblin/auth/tools.py | 2 +- mediagoblin/auth/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 94f23993..7123473d 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -198,7 +198,7 @@ def register_user(request, register_form): return None -def check_login_simple(username, password, username_might_be_email=False): +def check_login_simple(username, password): user = auth.get_user(username) if not user: _log.info("User %r not found", username) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index b62602b3..f063add8 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -96,7 +96,7 @@ def login(request): username = login_form.username.data if login_form.validate(): - user = check_login_simple(username, login_form.password.data, True) + user = check_login_simple(username, login_form.password.data) if user: # set up login in session From b1e02e0a702ffd085abdb5a4e1d3ca0b9c6192f1 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 27 May 2013 11:13:23 -0700 Subject: [PATCH 051/153] modified get_user function to take kwargs instead of username --- mediagoblin/auth/__init__.py | 5 +++-- mediagoblin/auth/tools.py | 2 +- mediagoblin/plugins/basic_auth/__init__.py | 18 ++++++++++-------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py index 8cb1f401..ab3d37e7 100644 --- a/mediagoblin/auth/__init__.py +++ b/mediagoblin/auth/__init__.py @@ -16,8 +16,9 @@ from mediagoblin.tools.pluginapi import hook_handle, hook_runall -def get_user(username): - return hook_handle("auth_get_user", username) +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): diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 7123473d..e2c84347 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -199,7 +199,7 @@ def register_user(request, register_form): def check_login_simple(username, password): - user = auth.get_user(username) + user = auth.get_user(username=username) if not user: _log.info("User %r not found", username) auth.fake_login_attempt() diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 375af335..71e96d73 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -26,17 +26,19 @@ def setup_plugin(): config = pluginapi.get_config('mediagoblin.pluginapi.basic_auth') -def get_user(username): - user = User.query.filter( - or_( - User.username == username, - User.email == username, - )).first() - return user +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(registration_form.username.data) + user = get_user(username=registration_form.username.data) if not user and 'password' in registration_form: user = User() user.username = registration_form.username.data From 0578d8b31b27af45fb8aa94bdb028972ed8adce4 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 27 May 2013 19:34:49 -0700 Subject: [PATCH 052/153] Conflicts: mediagoblin/auth/tools.py mediagoblin/auth/views.py mediagoblin/plugins/basic_auth/tools.py --- mediagoblin/auth/tools.py | 4 + mediagoblin/auth/views.py | 16 + .../i18n/ar/LC_MESSAGES/mediagoblin.mo | Bin 24638 -> 28177 bytes .../i18n/ar/LC_MESSAGES/mediagoblin.po | 720 ++++++++++-------- .../i18n/ca/LC_MESSAGES/mediagoblin.mo | Bin 24163 -> 25199 bytes .../i18n/ca/LC_MESSAGES/mediagoblin.po | 417 ++++++---- .../i18n/da/LC_MESSAGES/mediagoblin.mo | Bin 23311 -> 24330 bytes .../i18n/da/LC_MESSAGES/mediagoblin.po | 413 ++++++---- .../i18n/de/LC_MESSAGES/mediagoblin.mo | Bin 24819 -> 25761 bytes .../i18n/de/LC_MESSAGES/mediagoblin.po | 443 ++++++----- .../i18n/en/LC_MESSAGES/mediagoblin.po | 409 ++++++---- .../i18n/eo/LC_MESSAGES/mediagoblin.mo | Bin 24144 -> 25143 bytes .../i18n/eo/LC_MESSAGES/mediagoblin.po | 421 +++++----- .../i18n/es/LC_MESSAGES/mediagoblin.mo | Bin 24884 -> 25850 bytes .../i18n/es/LC_MESSAGES/mediagoblin.po | 437 ++++++----- .../i18n/fa/LC_MESSAGES/mediagoblin.mo | Bin 24126 -> 25146 bytes .../i18n/fa/LC_MESSAGES/mediagoblin.po | 409 ++++++---- .../i18n/fr/LC_MESSAGES/mediagoblin.mo | Bin 25195 -> 26152 bytes .../i18n/fr/LC_MESSAGES/mediagoblin.po | 429 ++++++----- .../i18n/he/LC_MESSAGES/mediagoblin.mo | Bin 25897 -> 27337 bytes .../i18n/he/LC_MESSAGES/mediagoblin.po | 476 +++++++----- .../i18n/ia/LC_MESSAGES/mediagoblin.mo | Bin 23302 -> 24326 bytes .../i18n/ia/LC_MESSAGES/mediagoblin.po | 411 ++++++---- .../i18n/is_IS/LC_MESSAGES/mediagoblin.mo | Bin 25008 -> 26226 bytes .../i18n/is_IS/LC_MESSAGES/mediagoblin.po | 468 +++++++----- .../i18n/it/LC_MESSAGES/mediagoblin.mo | Bin 24263 -> 25279 bytes .../i18n/it/LC_MESSAGES/mediagoblin.po | 422 +++++----- .../i18n/ja/LC_MESSAGES/mediagoblin.mo | Bin 23923 -> 24944 bytes .../i18n/ja/LC_MESSAGES/mediagoblin.po | 411 ++++++---- .../i18n/ko_KR/LC_MESSAGES/mediagoblin.mo | Bin 25185 -> 26202 bytes .../i18n/ko_KR/LC_MESSAGES/mediagoblin.po | 413 ++++++---- .../i18n/nl/LC_MESSAGES/mediagoblin.mo | Bin 23774 -> 24753 bytes .../i18n/nl/LC_MESSAGES/mediagoblin.po | 415 ++++++---- .../i18n/nn_NO/LC_MESSAGES/mediagoblin.mo | Bin 22783 -> 23760 bytes .../i18n/nn_NO/LC_MESSAGES/mediagoblin.po | 415 ++++++---- .../i18n/pl/LC_MESSAGES/mediagoblin.mo | Bin 24051 -> 25471 bytes .../i18n/pl/LC_MESSAGES/mediagoblin.po | 504 +++++++----- .../i18n/pt_BR/LC_MESSAGES/mediagoblin.mo | Bin 24133 -> 25166 bytes .../i18n/pt_BR/LC_MESSAGES/mediagoblin.po | 436 ++++++----- .../i18n/ro/LC_MESSAGES/mediagoblin.mo | Bin 24857 -> 25816 bytes .../i18n/ro/LC_MESSAGES/mediagoblin.po | 415 ++++++---- .../i18n/ru/LC_MESSAGES/mediagoblin.mo | Bin 31085 -> 32008 bytes .../i18n/ru/LC_MESSAGES/mediagoblin.po | 417 ++++++---- .../i18n/sk/LC_MESSAGES/mediagoblin.mo | Bin 24563 -> 25578 bytes .../i18n/sk/LC_MESSAGES/mediagoblin.po | 427 ++++++----- .../i18n/sl/LC_MESSAGES/mediagoblin.mo | Bin 23482 -> 24504 bytes .../i18n/sl/LC_MESSAGES/mediagoblin.po | 409 ++++++---- .../i18n/sq/LC_MESSAGES/mediagoblin.mo | Bin 24623 -> 25789 bytes .../i18n/sq/LC_MESSAGES/mediagoblin.po | 473 +++++++----- .../i18n/sr/LC_MESSAGES/mediagoblin.mo | Bin 23398 -> 24362 bytes .../i18n/sr/LC_MESSAGES/mediagoblin.po | 405 ++++++---- .../i18n/sv/LC_MESSAGES/mediagoblin.mo | Bin 23628 -> 24592 bytes .../i18n/sv/LC_MESSAGES/mediagoblin.po | 409 ++++++---- .../i18n/te/LC_MESSAGES/mediagoblin.mo | Bin 23544 -> 24563 bytes .../i18n/te/LC_MESSAGES/mediagoblin.po | 409 ++++++---- .../zh_TW.Big5/LC_MESSAGES/mediagoblin.mo | Bin 23342 -> 24306 bytes .../zh_TW.Big5/LC_MESSAGES/mediagoblin.po | 405 ++++++---- .../i18n/zh_TW/LC_MESSAGES/mediagoblin.mo | Bin 22667 -> 23678 bytes .../i18n/zh_TW/LC_MESSAGES/mediagoblin.po | 417 ++++++---- 59 files changed, 7525 insertions(+), 5150 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index e2c84347..48e0d572 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -17,6 +17,7 @@ import logging import wtforms +from sqlalchemy import or_ from mediagoblin import mg_globals from mediagoblin.db.models import User @@ -33,6 +34,8 @@ _log = logging.getLogger(__name__) _log = logging.getLogger(__name__) +_log = logging.getLogger(__name__) + def normalize_user_or_email_field(allow_email=True, allow_user=True): """ @@ -193,6 +196,7 @@ def register_user(request, register_form): # send verification email email_debug_message(request) send_verification_email(user, request) + return user return None diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index f063add8..d2220cb7 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -22,12 +22,20 @@ from mediagoblin.db.models import User from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools.mail import email_debug_message +<<<<<<< HEAD from mediagoblin.auth import forms as auth_forms from mediagoblin.auth.tools import (send_verification_email, register_user, send_fp_verification_email, check_login_simple) from mediagoblin import auth +======= +from mediagoblin.auth import lib as auth_lib +from mediagoblin.auth import forms as auth_forms +from mediagoblin.auth.lib import send_fp_verification_email +from mediagoblin.auth.tools import (send_verification_email, register_user, + check_login_simple) +>>>>>>> upstream/master def register(request): @@ -93,10 +101,18 @@ def login(request): login_failed = False if request.method == 'POST': +<<<<<<< HEAD username = login_form.username.data if login_form.validate(): user = check_login_simple(username, login_form.password.data) +======= + + username = login_form.data['username'] + + if login_form.validate(): + user = check_login_simple(username, login_form.password.data, True) +>>>>>>> upstream/master if user: # set up login in session diff --git a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo index 5e69858efe4b7e9c3ff8baac1edc00ae1d88a6d6..543830c8c1b9be63d23cdf7d4d45a27fe32b9e0d 100644 GIT binary patch literal 28177 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 delta 4846 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 TM&#>ToZIx;BI8${qN)D|eW6Xy diff --git a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po index 51c71c3a..1f086613 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 , 2011. -# Mena Rezk Eid , 2013. -# , 2011. -# , 2011. +# Jiyda , 2013 +# Majid Al-Dharrab , 2011 +# minaeid90 , 2013 +# OmarKH , 2011 +# OsamaK , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +23,39 @@ 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/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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "اسم المستخدم" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "كلمة السر" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "عنوان البريد الإلكتروني" -#: mediagoblin/auth/forms.py:78 -msgid "Username or email" +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" msgstr "" +#: mediagoblin/auth/forms.py:52 +msgid "Username or email" +msgstr "اسم المستخدم او الايميل" + +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "اسم مستخدم او ايميل غير صحيح." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "هذا الحقل لا يأخذ ايميل." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "هذا الحقل يحتاج ايميل." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "عفوًا، التسجيل غير متاح هنا." @@ -60,56 +66,56 @@ msgstr "عذرًا، لقد اختار مستخدم آخر هذا الاسم." #: mediagoblin/auth/views.py:72 msgid "Sorry, a user with that email address already exists." -msgstr "" +msgstr "عذرًا، لقد اختار مستخدم آخر هذا الايميل." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "مفتاح التحقق أو معرف المستخدم خاطئ" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "لقد قمت بالفعل بالتحقق من عنوان البريد الإلكتروني الخاص بك!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "أعدنا إرسال رسالة التحقق." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 msgid "" "If that email address (case sensitive!) is registered an email has been sent" " with instructions on how to change your password." -msgstr "" +msgstr "إذا كان هذا الايميل(حساس للحروف الكبيرة والصغيرة!) مُسجل, فقد تم إرسال ايميل به تعليمات عن كيفية تغيير رقمك السري." -#: mediagoblin/auth/views.py:261 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." -msgstr "" +msgstr "لم نتمكن من العثور على أحد له أسم المستخدم هذا." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." -msgstr "" +msgstr "لقد تم إرسال ايميل به تعليمات عن كيفية تغيير رقمك السري." -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." -msgstr "" +msgstr "تستطيع الآن الدخول باستخدام رقمك السري الجديد." -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -120,13 +126,13 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" " \n" " Markdown for formatting." -msgstr "" +msgstr "بامكانك استخدام ⏎\n⏎\nMarkdown للإدراج." #: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36 msgid "Tags" @@ -134,13 +140,13 @@ msgstr "الوسوم" #: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38 msgid "Separate tags by commas." -msgstr "" +msgstr "قم بفصل المحددات بفصلة." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "المسار" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "لا يمكن ترك المسار فارغًا" @@ -148,12 +154,12 @@ msgstr "لا يمكن ترك المسار فارغًا" 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/templates/mediagoblin/utils/license.html:20 msgid "License" -msgstr "" +msgstr "ترخيص" #: mediagoblin/edit/forms.py:50 msgid "Bio" @@ -165,48 +171,48 @@ msgstr "الموقع الإلكتروني" #: mediagoblin/edit/forms.py:58 msgid "This address contains errors" -msgstr "" +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:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" -msgstr "" +msgstr "تفضيل رخصة" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." -msgstr "" +msgstr "سوف تكون هذه رخصتك المبدئية في نماذج التحميل." -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" -msgstr "" +msgstr "ارسل لي رسالة عندما يقوم الاخرون بالتعليق على الميديا خاصتي" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" -msgstr "" +msgstr "لا يمكن ترك العنوان فارغًا" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" -msgstr "" +msgstr "وصف هذه المجموعة" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 msgid "" "The title part of this collection's address. You usually don't need to " "change this." -msgstr "" +msgstr "مقدمة عنوان هذه المجموعة, غالبا لن تحتاج لتغيره." -#: mediagoblin/edit/views.py:66 +#: mediagoblin/edit/forms.py:99 +msgid "Old password" +msgstr " كلمة السر القديمة" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "قم بإدخال رقمك السري القديم حتى تثبت انك صاحب هذا الحساب." + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "رقم سري جديد" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "يوجد ملف آخر بهذا المسار لدى هذى المستخدم." @@ -217,11 +223,11 @@ msgstr "أنت تحرّر وسائط مستخدم آخر. كن حذرًا أثن #: mediagoblin/edit/views.py:155 #, python-format msgid "You added the attachment %s!" -msgstr "" +msgstr "لقد قمت بإضافة مرفقة %s!" #: mediagoblin/edit/views.py:182 msgid "You can only edit your own profile." -msgstr "" +msgstr "يمكنك فقط تعديل حسابك الخاص" #: mediagoblin/edit/views.py:188 msgid "You are editing a user's profile. Proceed with caution." @@ -229,44 +235,63 @@ msgstr "أنت تحرّر ملف مستخدم آخر. كن حذرًا أثناء #: mediagoblin/edit/views.py:204 msgid "Profile changes saved" -msgstr "" +msgstr "تم حفظ تغيرات حسابك" -#: mediagoblin/edit/views.py:241 +#: mediagoblin/edit/views.py:240 +msgid "Account settings saved" +msgstr "تم حفظ خصائص حسابك" + +#: mediagoblin/edit/views.py:274 +msgid "You need to confirm the deletion of your account." +msgstr "يجب عليك تأكيد إلغاء حسابك." + +#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 +#, python-format +msgid "You already have a collection called \"%s\"!" +msgstr "أنت لديك مجموعة تدعى \"%s\"!" + +#: mediagoblin/edit/views.py:314 +msgid "A collection with that slug already exists for this user." +msgstr "توجد مجموعة اخرى بهذا المسار لهذا المستخدم." + +#: mediagoblin/edit/views.py:329 +msgid "You are editing another user's collection. Proceed with caution." +msgstr "أنت تعدل مجموعة مستخدم آخر. كن حذرًا أثناء العملية." + +#: mediagoblin/edit/views.py:348 msgid "Wrong password" msgstr "كلمة سر خاطئة" -#: mediagoblin/edit/views.py:252 -msgid "Account settings saved" +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" msgstr "" -#: mediagoblin/edit/views.py:286 -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 -#, python-format -msgid "You already have a collection called \"%s\"!" -msgstr "" - -#: mediagoblin/edit/views.py:326 -msgid "A collection with that slug already exists for this user." -msgstr "" - -#: mediagoblin/edit/views.py:343 -msgid "You are editing another user's collection. Proceed with caution." -msgstr "" - -#: mediagoblin/gmg_commands/theme.py:58 +#: 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 "لا يوجد مسار جيد لهذا الثيم\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 "" -#: mediagoblin/gmg_commands/theme.py:74 -msgid "However, old link directory symlink found; removed.\n" +#: 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 +299,59 @@ msgid "" "CSRF cookie not present. This is most likely the result of a cookie blocker " "or somesuch.
Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "CSRF كوكيز غير موجودة, وهذا من الممكن ان يكون نتيجة لمانع الكوكيز او شئ من هذا القبيل.
تأكد من أنك قمت بالسماح لخصائص الكوكيز لهذا الميدان." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" +msgstr "عذرا, انا لا ادعم هذا النوع من الملفات :(" + +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" -msgstr "" +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 OpenStreetMap" -msgstr "" +msgstr "عرض في OpenStreetMap" #: 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,88 +361,88 @@ msgid "" " Public - The client can't make confidential\n" " requests to the GNU MediaGoblin instance (e.g. client-side\n" " JavaScript client)." -msgstr "" +msgstr "سري - يستطيع العميل\nان يقوم بطلب نسخة من GNU MediaGoblin والتي من الممكن ان \nيعترضه وكيل المستخدم (مثلا الخادم من جانب العميل).
\nعام - لا يستطيع العميل ارسال طلبات سرية\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 required for public clients." -msgstr "" +msgstr "الرابط الموجه للبرنامج, هذا الحقل\nمطلوب لجمهور العملاء." #: 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:56 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/templates/mediagoblin/submit/collection.html:30 #: mediagoblin/templates/mediagoblin/submit/start.html:34 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68 msgid "Add" -msgstr "" +msgstr "اضف" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." -msgstr "" +msgstr "الملف المعطى لهذا النوع من الميديا غير صحيح." #: mediagoblin/submit/forms.py:26 msgid "File" msgstr "الملف" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "يجب أن تضع ملفًا." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "يا سلام! نُشرَت!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" -msgstr "" +msgstr "تم إضافة المجموعة \"%s\"!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "تأكد من بريدك الإلكترونى!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" -msgstr "" +msgstr "تسجيل خروج" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" -msgstr "" +msgstr "%(user_name)s's حساب" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" -msgstr "" +msgstr "تغيير خصائص الحساب" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -421,79 +450,32 @@ msgstr "" msgid "Media processing panel" msgstr "لوحة معالجة الوسائط" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" -msgstr "" - #: mediagoblin/templates/mediagoblin/base.html:96 +msgid "Log out" +msgstr "تسجيل خروج" + +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "أضف وسائط" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" +msgstr "إنشاء مجموعة جديدة" #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" -msgstr "" +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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: 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." -msgstr "" +msgstr "يمكنك متابعة عملية معالجة وسائط معرضك من هنا." #: mediagoblin/templates/mediagoblin/admin/panel.html:32 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32 @@ -513,34 +495,34 @@ msgstr "فشلت معالجة هذه الملفات:" #: mediagoblin/templates/mediagoblin/admin/panel.html:90 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86 msgid "No failed entries!" -msgstr "" +msgstr "لا توجد مداخل فاشلة!" #: mediagoblin/templates/mediagoblin/admin/panel.html:92 msgid "Last 10 successful uploads" -msgstr "" +msgstr "آخر 10 تحويلات ناجحة" #: mediagoblin/templates/mediagoblin/admin/panel.html:112 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 msgid "No processed entries, yet!" -msgstr "" +msgstr "لا يوجد مداخل مُعالجة بعد! " #: mediagoblin/templates/mediagoblin/auth/change_fp.html:28 #: mediagoblin/templates/mediagoblin/auth/change_fp.html:36 msgid "Set your new password" -msgstr "" +msgstr "قم بضبط رقمك السري الجديد" #: mediagoblin/templates/mediagoblin/auth/change_fp.html:39 msgid "Set password" -msgstr "" +msgstr "قم بضبط رقم سري" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23 #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31 msgid "Recover password" -msgstr "" +msgstr "استعادة كلمة السر" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34 msgid "Send instructions" -msgstr "" +msgstr "ارسل تعليمات" #: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 #, python-format @@ -592,6 +574,53 @@ 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 MediaGoblin, a GNU project." +msgstr "برعاية MediaGoblin, a GNU مشروع." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "تم النشر وفقا ل AGPL. Source code متاح." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "استكشف" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "اهلا, مرحبا بك في موقع MediaGoblin." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "هذا الموقع يقوم بتشغيل MediaGoblin, وهو برنامج استضافة ميديا فائق الروعة." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "ليس لديك واحد حتى الآن؟ انه سهل!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,18 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" -msgstr "" +msgstr "أضف مرفقة" #: mediagoblin/templates/mediagoblin/edit/attachments.html:61 #: mediagoblin/templates/mediagoblin/edit/delete_account.html:42 @@ -627,26 +656,36 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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,11 +697,15 @@ msgstr "تحرير %(media_title)s" #: 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:46 +msgid "Change your password." msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" -msgstr "" +msgstr "إلغِ حسابي" #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format @@ -681,42 +724,45 @@ msgstr "تحرير ملف %(username)s الشخصي" #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr "يتم تحديد الميديا ب: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 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 \n" "\t http://getfirefox.com!" -msgstr "" +msgstr "تستطيع الحصول على متصفح حديث ⏎\n»يمكنه تشغيل الصوت في ⏎\n» http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" -msgstr "" +msgstr "ملف أصلي" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:63 msgid "WebM file (Vorbis codec)" -msgstr "" +msgstr "ملف WebM (Vorbic كوديك)" +#: 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,65 +771,69 @@ msgstr "" #: 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:79 +msgid "PDF file" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" -msgstr "" +msgstr "تبديل التدوير" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 msgid "Perspective" -msgstr "" +msgstr "منظور" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 msgid "Front" -msgstr "" +msgstr "مقدمة" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Top" -msgstr "" +msgstr "أعلى" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 msgid "Side" -msgstr "" +msgstr "جانب" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 msgid "WebGL" -msgstr "" +msgstr "WebGL" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 msgid "Download model" -msgstr "" +msgstr "تحميل نموذج" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 msgid "File Format" -msgstr "" +msgstr "بنية الملف" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 msgid "Object Height" -msgstr "" +msgstr "طول الكائن" #: mediagoblin/templates/mediagoblin/media_displays/video.html:44 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 msgid "" "You can get a modern web browser that \n" " can play this video at \n" " http://getfirefox.com!" -msgstr "" +msgstr "تستطيع الحصول على متصفح حديث ⏎\n»يمكنه تشغيل هذا الفيديو في ⏎\n» http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/video.html:69 msgid "WebM file (640p; VP8/Vorbis)" -msgstr "" +msgstr "WebM ملف (640p; VP8/Vorbis)" #: mediagoblin/templates/mediagoblin/submit/collection.html:26 msgid "Add a collection" @@ -792,27 +842,27 @@ msgstr "إضافة مجموعة" #: mediagoblin/templates/mediagoblin/submit/start.html:23 #: mediagoblin/templates/mediagoblin/submit/start.html:30 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 %(username)s" -msgstr "" +msgstr "%(collection_title)s بواسطة %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/collection.html:52 #: mediagoblin/templates/mediagoblin/user_pages/media.html:79 msgid "Edit" -msgstr "" +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 +873,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 "%(username)s's collections" -msgstr "" +msgstr "%(username)s'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 "" "%(username)s's media with tag %(tag)s" -msgstr "" +msgstr "\n%(username)s\n\n's ميديا بالمحدد\n\n%(tag)s\n" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -866,40 +916,44 @@ msgstr "وسائط %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/media.html:38 #, python-format msgid "❖ Browsing media by %(username)s" -msgstr "" +msgstr "❖ اختيار الميديا بواسطة %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" -msgstr "" +msgstr "أضف تعليق" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" -msgstr "" +msgstr "اضف هذا التعليق" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" 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,7 +962,7 @@ 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 @@ -970,7 +1024,7 @@ msgstr "لم يعبئ هذا العضو بيانات ملفه بعد." #: mediagoblin/templates/mediagoblin/user_pages/user.html:124 msgid "Browse collections" -msgstr "" +msgstr "تحديد مجموعة" #: mediagoblin/templates/mediagoblin/user_pages/user.html:137 #, python-format @@ -991,59 +1045,59 @@ msgstr "لا يبدو أنه توجد أي وسائط هنا حتى الآن..." #: 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 "" +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 msgid "Oops!" @@ -1051,36 +1105,60 @@ msgstr "ويحي!" #: mediagoblin/tools/response.py:36 msgid "An error occured" -msgstr "" +msgstr "حدث خطأ" #: mediagoblin/tools/response.py:51 msgid "Operation not allowed" -msgstr "" +msgstr "غير مسموح بهذه العملية" #: mediagoblin/tools/response.py:52 msgid "" "Sorry Dave, I can't let you do that!

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 "عذرا ديف, لا استطيع ترك تفعل هذا!

لقد حاولت تشغيل خاصية ليست مسموحة لك. هل كنت تحاول إلغاء جميع حسابات المستخدمين مجددا؟" #: mediagoblin/tools/response.py:60 msgid "" "There doesn't seem to be a page at this address. Sorry!

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 "" +msgstr "تعليق" #: mediagoblin/user_pages/forms.py:25 msgid "" "You can use Markdown for" " formatting." -msgstr "" +msgstr "بامكانك استخدام Markdown للإدراج." #: mediagoblin/user_pages/forms.py:31 msgid "I am sure I want to delete this" @@ -1088,87 +1166,91 @@ 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 "" +msgstr "إدراج ملاحظة" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" +msgstr "قام بالتعليق على مشاركتك" + +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." -msgstr "" +msgstr "عذرا, لقد قمت بادخال تعليق فارغ." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" -msgstr "" +msgstr "لقد تم إرسال تعليقك!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." -msgstr "" +msgstr "من فضلك قم بفحص المداخل وقم بالمحاولة مرة أخرى." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" -msgstr "" +msgstr "يجب عليك إختيار أو إضافة مجموعة" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" -msgstr "" +msgstr "\"%s\" توجد بالفعل في المجموعة \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" -msgstr "" +msgstr "\"%s\" أُضيفت للمجموعة \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." -msgstr "" +msgstr "لقد قمت بإلغاء الميديا." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." -msgstr "" +msgstr "لقد قمت بإلغاء المادة من المجموعة." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" -msgstr "" +msgstr "لقد قمت بإلغاء المجموعة \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 msgid "" "You are about to delete another user's collection. Proceed with caution." -msgstr "" +msgstr "أنت على وشك حذف مجموعة مستخدم آخر. كن حذرا." diff --git a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo index 495ef726102341a18eeaa2cf1f90027a45e34394..ec01d7f704a98297d3498376e438ec88c01beed6 100644 GIT binary patch delta 5215 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 W!|1uXjDl~~-*=Z^Fq*!4>E8im9!i}6 delta 4329 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 DS+!L? diff --git a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po index 28bdca82..9ebbdf18 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 , 2011. -# , 2011. -# , 2012. +# Al fred , 2011 +# Al fred , 2011 +# skarbat , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +21,39 @@ msgstr "" "Language: ca\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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Nom d'usuari" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Contrasenya" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Adreça electrònica" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Nom d'usuari o correu" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Ho sentim, el registre està desactivat en aquest cas." @@ -61,54 +66,54 @@ msgstr "Lamentablement aquest usuari ja existeix." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "Torna'm a enviar el correu de verificació" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -119,7 +124,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -135,11 +140,11 @@ msgstr "Etiquetes" 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:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Llimac" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "El llimac no pot ésser buit" @@ -167,45 +172,45 @@ 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:67 -msgid "New password" -msgstr "Nova contrasenya" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "Contrasenya antiga" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nova contrasenya" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Ja existeix una entrada amb aquest llimac per aquest usuari" @@ -230,44 +235,63 @@ msgstr "Esteu editant el perfil d'un usuari. Aneu amb compte" 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:240 msgid "Account settings saved" msgstr "Els detalls del compte s'han guardat" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 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:348 +msgid "Wrong password" +msgstr "Contrasenya errònia" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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,12 +299,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "La transformació del vídeo ha fallat" @@ -347,7 +375,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:56 msgid "The client {0} has been registered!" msgstr "El client {0} ha sigut enregistrat!" @@ -366,7 +394,7 @@ msgstr "" msgid "Add" msgstr "Afegir" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Aquest tipus de fitxer no és vàlid." @@ -374,45 +402,45 @@ msgstr "Aquest tipus de fitxer no és vàlid." msgid "File" msgstr "Fitxer" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Heu d'escollir un fitxer." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Visca! S'ha enviat!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "S'ha afegit la col.leccio \"%s\"!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Verifica el teu correu electrònic" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 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/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -420,72 +448,25 @@ msgstr "Modificar els ajustaments del compte" msgid "Media processing panel" msgstr "Quadre de processament de fitxers" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Tots els fitxers" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Alliberat segons la AGPL. Codi font disponible." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 "Hola, una benvinguda al MediaGoblin!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "El lloc esta usant MediaGoblin, una gran i extraordinària peça de software per allotjar mitjans." - -#: 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 "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 -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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Crear un compte a aquest lloc \no\n Preparar MediaGoblin al teu propi servidor" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Mitjans més recents" @@ -591,6 +572,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Alliberat segons la AGPL. Codi font disponible." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Explorar" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Hola, una benvinguda al MediaGoblin!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "El lloc esta usant MediaGoblin, una gran i extraordinària peça de software per allotjar mitjans." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +msgid "Don't have one yet? It's easy!" +msgstr "No en tens una encara? Es fàcil!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -603,13 +631,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -626,12 +654,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +680,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,7 +697,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -684,6 +726,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -708,6 +751,7 @@ msgid "" msgstr "Pots obtenir un navegador web modern que \n »podrà reproduir l'àudio, a \n » http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Arxiu original" @@ -716,6 +760,7 @@ msgstr "Arxiu original" msgid "WebM file (Vorbis codec)" msgstr "Arxiu WebM (Vorbis codec)" +#: 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,6 +771,10 @@ msgstr "Arxiu WebM (Vorbis codec)" msgid "Image for %(media_title)s" msgstr "Imatge per %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -824,7 +873,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 +916,28 @@ msgstr "%(username)s's media" msgid "❖ Browsing media by %(username)s" msgstr "❖ Navegant mitjà per a %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Afegeix un comentari" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Afegit el

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1040,7 +1093,7 @@ msgstr "més antic" 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" @@ -1070,6 +1123,30 @@ msgid "" " 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 "" @@ -1101,73 +1178,77 @@ msgstr "-- Sel.leccionar --" msgid "Include a note" msgstr "Incluir una nota" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "comentat al teu post" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Uups, el teu comentari era buit." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "El teu comentari s'ha publicat!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Has esborrat el mitjà" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, 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:422 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:430 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 index 6b6827f035faed0e2352b32997ca28964ad2f7c7..53e3fedf393de44133cddd6144eebdd0e87ded4d 100644 GIT binary patch delta 5147 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 gQMoMeVr8w, 2012. -# Olle Jonsson , 2012. -# Tanja Trudslev , 2012. +# Morten Juhl-Johansen Zölde-Fejér , 2012 +# Olle Jonsson , 2012 +# ttrudslev , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +21,39 @@ 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/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "" - -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Brugernavn" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Kodeord" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Email adresse" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Brugernavn eller email" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Desværre, registrering er ikke muligt på denne instans" @@ -61,54 +66,54 @@ msgstr "Desværre, det brugernavn er allerede brugt" 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "Email til godkendelse sendt igen." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -119,7 +124,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -135,11 +140,11 @@ msgstr "Tags" msgid "Separate tags by commas." msgstr "Separer tags med kommaer." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "" @@ -167,45 +172,45 @@ 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:67 -msgid "New password" -msgstr "Ny kodeord" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "Gammelt kodeord" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Ny kodeord" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "" @@ -230,44 +235,63 @@ msgstr "Du er ved at ændre en bruger's profil. Pas på." 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:240 msgid "Account settings saved" msgstr "Kontoindstillinger gemt" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 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:348 +msgid "Wrong password" +msgstr "Forkert kodeord" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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 "" + +#: 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,12 +299,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -347,7 +375,7 @@ 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:56 msgid "The client {0} has been registered!" msgstr "Klienten {0} er blevet registreret!" @@ -366,7 +394,7 @@ msgstr "" msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Forkert fil for medietypen." @@ -374,45 +402,45 @@ msgstr "Forkert fil for medietypen." msgid "File" msgstr "Fil" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Du må give mig en fil" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Juhuu! Delt!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Bekræft din email!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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 "Log ind" -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -420,72 +448,25 @@ msgstr "" msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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/templates/mediagoblin/root.html:38 -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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "" @@ -591,6 +572,53 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Udforsk" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +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 MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +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:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -603,13 +631,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -626,12 +654,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +680,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 "" @@ -659,7 +697,11 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -684,6 +726,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -708,6 +751,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -716,6 +760,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +771,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -824,7 +873,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 "" @@ -867,23 +916,27 @@ msgstr "" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1040,7 +1093,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1070,6 +1123,30 @@ msgid "" " 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 "" @@ -1101,73 +1178,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo index 5ae794fab6653d2942ecaa68dddbe807d6c1bee2..a07400aefed55e4f45688d84c34f4b0d3e8214ca 100644 GIT binary patch delta 5264 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 S)JxdWUuWzONZ1F~RsRP^dtCzn delta 4427 zcmaLZdvuLg8prXS3n38%kpz)fh+BjtB#203Bt+aVt-JQbc_oMB9COZzDML@0VhuxP zIW<$GI<%&yI;fu3!kD!f^rAYgVRX5SWp#{>YIV^p{$M)u{pCGt&3|*&Nj`hO@4NSY z_OthXlRY2De19q?bfZ)JcEjfzetPh;IzhGneXh4RCX?#lF$*7KK6dY5%u_fCyWuae z3+}_NcmmttMU27g*bZ;tKkzOV8WS>~bu^}k3$ZE248ajN59_cWp2m&za2H2X4|H}0 zIDm1~&mdixk1!dppaS^{iPb#8wwT04J(r4HGJUZ<7|Q0e*`~_!cU#_puWm!yR}YTjLValZ_3S#`xx!6#C=uQ7O8BiFgC~ znmhbzS(P+ndQxwLtFRv`@YhitpGOUN5gE(eMg{mJdOtbc7?NnZpq}fCp?C@-DJb$X z)Bx4U*Le7)wOtpzz6-UcCs3(9i)w!f75Ej@9=eT;Y2q@R{<@=UF4rn@|J2i)w!s707jD z70e@4$~#(4yPl}cnv2S0sEC4QI0}{Gxu}SJsD{r+>l;uhZ$hozPTYWJQ0*r6at3ta zkEpLgW%f^~i9AFFoBCDA17jJ zUt=oKh2wA^YS-UGFDCVKcK<3=;M;H}zKv7xKd3;a5ZxZeH$SB?7&AG{7EVHS*noV^ zrl{{BF_;@T3*!eG^CHegy*aPqbC}3hFT`co3SYxTxEHmgaf}{^DcExUQz^9JLN`>( zd!sg05o!iiXrT)=&^lDd@1g=dihAyEn1J_C?H^)$Y@6rov2@h)#Yn7XW*+%}n!*cQ zsKQG)7Bfl5aCBig?!Zxa6<1?dqF9e%WKt$0-&vwc98cYY+wd^jSW)2Yt^KHsoU12$Sn4mMI{r1b#e=Af97Sd9 zWYiC$_s@qYjONB=ydJ}`;Pu4*F!zg`NHdC^K*nM@*Bem-9KkO5Y1A(F4Oh@gBO*j>AqBcuDY3hvgQK|Kz z+O5PyT!-nn1>eFqQO`{)bCz}<>fCR~{`d~2==@)yptZS+nRp-7u)|Z%z!~@k^$H|- z^Dop)`jk6sUx0ccO~;;CiwbN5D&QtmX5K&rdIZ(}6zcDf`3r?Kyo*}XxG~PAOGkB7 zfx12!)jf1CfVLpF%t=&+;>Yn{7IwowqI(?qR|gh{ zR-5V=YDO1PYxw{*gQO~Bcr}=A$g-L$)C@OZYdnC;$a|;>e1L86uTig|`n`n;B#tPw zBpDOPe{TwdxS-=Q4U^G@@#sSZ5Ja7hpJ6Y2AG_lhsP^BZ0#2)T0?0?TD~;ACVgmKq zsP@ldS6mySph#aq4ZJ5>KZKgeQRH1?&fq3|gxaL*COYqj-MEzcIVAh0Xp)o3Rj3)h zjGJ*Ew#A_=yfQHw`(bDS1*POARD<831~`Bn@DtQtxQ5Eecc_k$w@uZeNP4 zsINyoufMUHSx=-(Ga6}Pw&G~Ki3fFmma}(0#eq8i%@lMjvYvJ}St%A!Uy1|qRaE33 z;`5mBj5E_0kr|j{ScciNom1q(0QFkb#I9i+-ii7xwxfO@Eyg!LP|$A9n&WJaaj1G7 z7Ge|Xc>WnR(~nT6Xn7Pj8ZHp;XyWt=lggLs6LokF3@er~KCV3v$*cWCYg>kqa zwTbRW>&4`MBlR`77F#WFX1)>gsGme)F!#`pPnUf~INeBQhY0x7Wy^9y*0?{KSNXh}hFZa$yH zNv=RJZlIjwAu*KV+EPp$2>y|nhPpw(w3+2N*=Ys&UBw*T~z zB};5?u%3~EmaF0aEJE$54snsyWue$`%9sJ+`D4l>pO0yXiByjLRon2|Ug-(Tf_0~l z)Y;*z$&Ha+lP|@FS4>+TX+8aHOytgt$~KYm`P&oP&Gj|, 2011. -# , 2011. -# Elrond , 2011-2012. -# Elrond , 2013. -# , 2011, 2012. -# Jakob Kramer , 2012-2013. -# Jan-Christoph Borchardt , 2011. -# Jan-Christoph Borchardt , 2011, 2012. -# , 2011. -# , 2011. -# Rafael Maguiña , 2011. -# , 2012. -# Vinzenz Vietzke , 2012. -# Vinzenz Vietzke , 2011. +# piratenpanda , 2011 +# cwebber , 2011 +# Elrond , 2011-2012 +# Elrond , 2013 +# Jakob Kramer , 2011, 2012 +# Jakob Kramer , 2012-2013 +# Jan-Christoph Borchardt , 2011 +# Jan-Christoph Borchardt , 2011, 2012 +# Keyzo , 2011 +# Elrond , 2011 +# Art O. Pal , 2011 +# spaetz , 2012 +# Vinzenz Vietzke , 2012 +# Vinzenz Vietzke , 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 \n" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" +"Last-Translator: cwebber \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,34 +32,39 @@ msgstr "" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "Ungültiger Benutzername oder E-Mail-Adresse." - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "Dieses Feld akzeptiert keine E-Mail-Adressen." - -#: mediagoblin/auth/forms.py:30 -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 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Benutzername" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Passwort" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "E-Mail-Adresse" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Benutzername oder E-Mail-Adresse" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Ungültiger Benutzername oder E-Mail-Adresse." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Dieses Feld akzeptiert keine E-Mail-Adressen." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Dieses Feld benötigt eine E-Mail-Adresse." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Benutzerregistrierung ist auf diesem Server leider deaktiviert." @@ -72,54 +77,54 @@ msgstr "Leider gibt es bereits einen Benutzer mit diesem Namen." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "Aktivierungsmail wurde erneut versandt." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "Es konnte niemand mit diesem Benutzernamen gefunden werden." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -130,7 +135,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -146,11 +151,11 @@ msgstr "Schlagwörter" msgid "Separate tags by commas." msgstr "Kommaseparierte Schlagwörter" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Kurztitel" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Bitte gib einen Kurztitel ein" @@ -178,45 +183,45 @@ 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:67 -msgid "New password" -msgstr "Neues Passwort" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "Bevorzugte Lizenz" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 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 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Beschreibung dieser Sammlung" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "Altes Passwort" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Neues Passwort" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Diesen Kurztitel hast du bereits vergeben." @@ -241,44 +246,63 @@ msgstr "Du bearbeitest das Profil eines anderen Nutzers. Sei bitte vorsichtig." 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:240 msgid "Account settings saved" msgstr "Kontoeinstellungen gespeichert" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 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:329 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:348 +msgid "Wrong password" +msgstr "Falsches Passwort" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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,12 +310,16 @@ msgid "" "domain." msgstr "Das CSRF cookie ist nicht vorhanden. Das liegt vermutlich an einem Cookie-Blocker oder ähnlichem.
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:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Videokonvertierung fehlgeschlagen" @@ -358,17 +386,17 @@ 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:56 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/templates/mediagoblin/submit/collection.html:30 @@ -377,7 +405,7 @@ msgstr "" msgid "Add" msgstr "Hinzufügen" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Die Datei stimmt nicht mit dem gewählten Medientyp überein." @@ -385,45 +413,45 @@ msgstr "Die Datei stimmt nicht mit dem gewählten Medientyp überein." msgid "File" msgstr "Datei" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Du musst eine Datei angeben." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "JAAA! Geschafft!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "Sammlung »%s« hinzugefügt!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Bitte bestätige Deine E-Mail-Adresse!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "abmelden" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "%(user_name)ss Konto" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Kontoeinstellungen ändern" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -431,72 +459,25 @@ msgstr "Kontoeinstellungen ändern" msgid "Media processing panel" msgstr "Medienverarbeitung" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "Abmelden" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Medien hinzufügen" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Neues Album erstellen" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by MediaGoblin, a GNU project." -msgstr "Läuft mit MediaGoblin, einem GNU-Projekt." - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Veröffentlicht unter der AGPL (Quellcode)." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "Bild eines gestressten Goblins" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Entdecken" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Hallo du, willkommen auf dieser MediaGoblin-Seite!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Diese Webseite setzt MediaGoblin ein, eine großartige Software für Medienhosting." - -#: 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 "Melde Dich mit Deinem MediaGoblin-Konto an, um eigene Medien hinzuzufügen, andere zu kommentieren und vieles mehr." - -#: mediagoblin/templates/mediagoblin/root.html:38 -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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Registriere dich auf dieser Seite oder Installiere MediaGoblin auf deinem eigenen Server" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Neuste Medien" @@ -602,6 +583,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "Läuft mit MediaGoblin, einem GNU-Projekt." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Veröffentlicht unter der AGPL (Quellcode)." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Entdecken" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Hallo du, willkommen auf dieser MediaGoblin-Seite!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Diese Webseite setzt MediaGoblin ein, eine großartige Software für Medienhosting." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +msgid "Don't have one yet? It's easy!" +msgstr "Hast du noch keinen? Das geht ganz einfach!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -614,13 +642,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Anhang hinzufügen" @@ -637,12 +665,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +691,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,7 +708,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "Mein Konto löschen" @@ -695,6 +737,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -719,6 +762,7 @@ msgid "" msgstr "Hol dir auf http://getfirefox.com einen modernen Webbrowser, der dieses Audiostück abspielen kann!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Originaldatei" @@ -727,6 +771,7 @@ msgstr "Originaldatei" msgid "WebM file (Vorbis codec)" msgstr "WebM-Datei (Vorbis-Codec)" +#: 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,6 +782,10 @@ msgstr "WebM-Datei (Vorbis-Codec)" msgid "Image for %(media_title)s" msgstr "Bild für %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -835,7 +884,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 +927,28 @@ msgstr "%(username)ss Medien" msgid "❖ Browsing media by %(username)s" msgstr "❖ Medien von %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Einen Kommentar schreiben" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Veröffentlicht am

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1051,7 +1104,7 @@ msgstr "älter" 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." @@ -1081,6 +1134,30 @@ msgid "" " deleted." msgstr "Tut uns Leid, aber unter der angegebenen Adresse gibt es keine Seite!

Wenn du sicher bist, dass die Adresse stimmt, wurde die Seite eventuell verschoben oder gelöscht." +#: 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 "Kommentar" @@ -1112,73 +1189,77 @@ msgstr "-- Auswählen --" msgid "Include a note" msgstr "Notiz anfügen" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "hat dein Medium kommentiert" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Hoppla, der Kommentartext fehlte." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Dein Kommentar wurde angenommen!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Du hast das Medium gelöscht." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, 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:422 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:430 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..913c2ec1 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-05-27 13:54-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,34 +17,39 @@ 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." -msgstr "" - -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "" @@ -57,53 +62,53 @@ msgstr "" msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -114,7 +119,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -131,11 +136,11 @@ msgstr "" msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "" @@ -163,45 +168,45 @@ 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:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "" @@ -226,44 +231,63 @@ msgstr "" msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,11 +295,15 @@ msgid "" "this domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "" +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + #: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -347,7 +375,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -366,7 +394,7 @@ msgstr "" msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "" @@ -374,45 +402,45 @@ msgstr "" msgid "File" msgstr "" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -420,76 +448,25 @@ msgstr "" msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU " -"project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, " -"an extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an " -"account at this site\n" -" or\n" -" Set up MediaGoblin on " -"your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "" @@ -594,6 +571,57 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by MediaGoblin, a GNU " +"project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, " +"an extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an " +"account at this site\n" +" or\n" +" Set up MediaGoblin on " +"your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -606,13 +634,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -629,12 +657,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +683,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,7 +700,11 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -687,6 +729,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -711,6 +754,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -719,6 +763,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +774,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -827,7 +876,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 +920,27 @@ msgstr "" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1042,7 +1095,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1072,6 +1125,30 @@ msgid "" "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 "" @@ -1103,74 +1180,78 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index ac74a68b5930ef0d8de43bf026165fe424c90025..406b269f2e25e8fc075ccd2fbb19ebbf7c26a824 100644 GIT binary patch delta 5311 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 delta 4406 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 diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po index e7785d73..eb1ec1ec 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: -# , 2013. -# , 2011-2012. -# Fernando Inocencio , 2011. -# , 2011. +# aleksejrs , 2013 +# aleksejrs , 2011-2012 +# Fernando Inocencio , 2011 +# tiguliano , 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 \n" -"Language-Team: LANGUAGE \n" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" +"Last-Translator: cwebber \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,34 +22,39 @@ msgstr "" "Language: eo\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "Nevalida ensalutnomo aŭ retpoŝtadreso." - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "Ĉi tiu kampo ne akceptas retpoŝtadresojn." - -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "Ĉi tiu kampo postulas retpoŝtadreson." - -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Uzantnomo" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Pasvorto" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Retpoŝtadreso" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Salutnomo aŭ retpoŝtadreso" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Nevalida ensalutnomo aŭ retpoŝtadreso." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Ĉi tiu kampo ne akceptas retpoŝtadresojn." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Ĉi tiu kampo postulas retpoŝtadreson." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Bedaŭrinde, registrado estas malaktivigita en tiu ĉi instalaĵo." @@ -62,54 +67,54 @@ msgstr "Bedaŭrinde, uzanto kun tiu nomo jam ekzistas." 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:182 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:188 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:206 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:214 msgid "You've already verified your email address!" msgstr "Vi jam konfirmis vian retpoŝtadreson!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "Resendi vian kontrol-mesaĝon." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "Trovitas neniu kun tiu ensalutnomo." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -120,7 +125,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -136,11 +141,11 @@ msgstr "Etikedoj" 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:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "La distingiga adresparto" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "La distingiga adresparto ne povas esti malplena" @@ -168,45 +173,45 @@ 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:67 -msgid "New password" -msgstr "La nova pasvorto" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "Permesila prefero" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 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:94 +#: mediagoblin/edit/forms.py:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "La malnova pasvorto" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "La nova pasvorto" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Ĉi tiu uzanto jam havas dosieron kun tiu distingiga adresparto." @@ -231,44 +236,63 @@ msgstr "Vi redaktas profilon de alia uzanto. Agu singardeme." 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:240 msgid "Account settings saved" msgstr "Kontagordoj estis konservitaj" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 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:329 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:348 +msgid "Wrong password" +msgstr "Malĝusta pasvorto" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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,12 +300,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Malsukcesis transkodado de filmo" @@ -348,7 +376,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -367,7 +395,7 @@ msgstr "" msgid "Add" msgstr "Aldoni" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "La provizita dosiero ne konformas al la informtipo." @@ -375,45 +403,45 @@ msgstr "La provizita dosiero ne konformas al la informtipo." msgid "File" msgstr "Dosiero" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Vi devas provizi dosieron." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Hura! Alŝutitas!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "Kolekto «%s» aldonitas!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Konfirmu viecon de la retpoŝtadreso!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "elsaluti" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "Konto de %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Ŝanĝi kontagordojn" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -421,72 +449,25 @@ msgstr "Ŝanĝi kontagordojn" msgid "Media processing panel" msgstr "Kontrolejo pri dosierpreparado." -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "Elsaluti" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Aldoni dosieron" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Krei novan kolekton" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by MediaGoblin, a GNU project." -msgstr "Funkcias per MediaGoblin, unu el la projektoj de GNU." - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Disponigita laŭ la permesilo AGPL. Haveblasfontotekstaro." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "Bildo de zorgigita koboldo" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Ĉirkaŭrigardi" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Saluton, kaj bonvenon al ĉi tiu MediaGoblina retpaĝaro!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Ĉi tiu retpaĝaro funkcias per MediaGoblin, eksterordinare bonega programaro por gastigado de aŭd‐vid‐dosieroj." - -#: 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 "Por aldoni viajn proprajn dosierojn, afiŝi komentariojn ktp, vi povas ensaluti je via MediaGoblina konto." - -#: mediagoblin/templates/mediagoblin/root.html:38 -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 -msgid "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Kreu konton en ĉi tiu retejo\n aŭ\n ekfunkciigu MediaGoblin’on en via propra servilo" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Laste aldonitaj dosieroj" @@ -592,6 +573,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "Funkcias per MediaGoblin, unu el la projektoj de GNU." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Disponigita laŭ la permesilo AGPL. Haveblasfontotekstaro." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Ĉirkaŭrigardi" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Saluton, kaj bonvenon al ĉi tiu MediaGoblina retpaĝaro!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Ĉi tiu retpaĝaro funkcias per MediaGoblin, eksterordinare bonega programaro por gastigado de aŭd‐vid‐dosieroj." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +msgid "Don't have one yet? It's easy!" +msgstr "Ĉu vi ankoraŭ ne havas tian? Ne malĝoju!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -604,13 +632,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Aldoni kundosieron" @@ -627,12 +655,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +681,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,7 +698,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "Forigi mian konton." @@ -685,6 +727,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -709,6 +752,7 @@ msgid "" msgstr "Vi povas akiri modernan TTT-legilon, kapablan \n\tsonigi la registraĵon ĉe \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "originalan dosieron" @@ -717,6 +761,7 @@ msgstr "originalan dosieron" msgid "WebM file (Vorbis codec)" msgstr "WebMan dosieron (kun Vorbisa kodaĵo)" +#: 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,6 +772,10 @@ msgstr "WebMan dosieron (kun Vorbisa kodaĵo)" msgid "Image for %(media_title)s" msgstr "Bildo de «%(media_title)s»" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -825,7 +874,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 +917,28 @@ msgstr "Dosieroj de %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "❖ Просмотр файлов пользователя %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Aldoni komenton" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Aldonita je

\n

la %(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1041,7 +1094,7 @@ msgstr "malpli nova" 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" @@ -1071,6 +1124,30 @@ msgid "" " 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 "Komenti" @@ -1102,73 +1179,77 @@ msgstr "-- Elektu --" msgid "Include a note" msgstr "Rimarko" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "komentis je via afiŝo" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Oj, via komento estis malplena." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Via komento estis afiŝita!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Vi forigis la dosieron." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, 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:422 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:430 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 index e2df07310aeec5e44a90eb9a22b31f0676bbcd83..ececfb2eb6c9f6c4b1946316e0719edf3ef91fd9 100644 GIT binary patch delta 5195 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 Nez?p+@wZmj{s-hqQ&s=~ delta 4336 zcmaLZdr*|u8OQMhq96(a%2k0^40uH@0ue-miVAoac<~baPDfl{e!=0Fb zM=%14PUVjO;eTk#Zjz=fnI1D9eV^P8X1=!3gZDLRLdcoq3J|KQit zsw5hdMn3{qU~g35J5U3kLQQxcnaf;91^764KPt%>l4!c2p36di7>!~YihLMqf-22f-2Dh)Pn1i$vcXXunN1f)nCF*$egA#>Co=aLT#FI)XHaIFRVk=avd_K*^64hNmPo@p)&RjszkSg z_wNVqKlanmz+DJOweE$Atb|{x-7Hki7Nat<5|!!})WjQ66YWR6e*zUqD^dm1hDv#i z<-C`M+N}Line-RZ&1t^6)(C1K=S*Hcjw_CsZ)Ea)hlPQMC& zi91k%Ry^Yz*JU_>{!UbeE?}O{|MxUzaiM3XF*VqXTIrVMHpD{1vOw=dmWqbi6+3NYY7~A7JI1k@Lm9!nRx5HR`dj8{SL~tPmmGWMwO;w0m zK?PdqLQT|y8hAe{&_k%_{(|B79qRpu7>ymXojsO>dcFvW)l_Gb|L19};z9*pz>%0r zI-W%rmf=<$f|s!w6Nq9p+Q_0za;{UNQ8EjKLQ4D}`rhD6%h5yZlR3Chnmo z?82GUN)m7(_C~U6HefTJ!mqKioWF>eJ<9o<*n+d@pTI1%MmzsAj=^{6uN_VPZ5mmG zmxhN?5nno)L zKZ|`abds}Y24D^SAK`qR|I;+I;(?Q$+La)GkxeZ=p{)TJ^Q^48ulTGsq4b|*C>RiXo zcK)-OgzMVH|LT6 zG#aDH;{bFA-Go}vN2p`=Ij+J7XkpU}&Y#;Ym_+|gjKqDYlphK9KMi^@c>OEXDfuUw zjLgOi%MOkCm0cZ^Xt&1f4!0~{L!@N|UXAsJWG)&sYU!CP!-ekP)AG;fjZ%M7&E-gBe zHz+%|z{(q3l3S3STa=p{IcZ|{6!(jsMvu>%T}~h+R(`G?;=9nw%`M3d^nLbvh@Dlu ztDm*p>#}N=yS+^=%k8z?jZJQ=(bMGdmFBqqyC4?L((G4bC-$lIHa5AIxUBK+T92#F zw_u5fcf3~9a;v_{-fu}(&C&C(6jptavYbwd0&r&i?jk}@2)j+U~x?|6;O|*B` GR{sZuSzez2 diff --git a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po index 21dce0b1..03e755ab 100644 --- a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po @@ -3,24 +3,24 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# , 2011, 2012. -# , 2011. -# , 2011-2012. -# Javier Di Mauro , 2011. -# , 2011. -# , 2011, 2012. -# , 2012. -# Laura Arjona Reina , 2013. -# Mario Rodriguez , 2011. -# , 2011. -# , 2012. -# , 2012. +# aleksejrs , 2011, 2012 +# ekenbrand , 2011 +# nvjacobo , 2011-2012 +# Javier Di Mauro , 2011 +# case , 2011 +# juanman , 2011, 2012 +# larjona , 2012 +# larjona , 2013 +# Mario Rodriguez , 2011 +# Manuel Urbano Santos , 2011 +# shackra , 2012 +# Elesa , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" "Language-Team: Spanish (http://www.transifex.com/projects/p/mediagoblin/language/es/)\n" "MIME-Version: 1.0\n" @@ -30,34 +30,39 @@ msgstr "" "Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "Nombre de usuario o correo electrónico inválido." - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "Este campo no acepta direcciones de correo." - -#: mediagoblin/auth/forms.py:30 -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 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Nombre de usuario" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Contraseña" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Dirección de correo electrónico" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Nombre de usuario o email" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Nombre de usuario o correo electrónico inválido." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Este campo no acepta direcciones de correo." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Este campo requiere una dirección de correo." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Lo sentimos, el registro está deshabilitado en este momento." @@ -70,54 +75,54 @@ msgstr "Lo sentimos, ya existe un usuario con ese nombre." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "Se reenvió tu correo electrónico de verificación." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 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 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -128,7 +133,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -144,11 +149,11 @@ msgstr "Etiquetas" 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:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Ficha" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "La ficha no puede estar vacía" @@ -176,45 +181,45 @@ 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:67 -msgid "New password" -msgstr "Nueva contraseña" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "Preferencias de licencia" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 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 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "Vieja contraseña" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nueva contraseña" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Una entrada con esa ficha ya existe para este usuario." @@ -239,44 +244,63 @@ msgstr "Estás editando un perfil de usuario. Procede con precaución." 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:240 msgid "Account settings saved" msgstr "las configuraciones de cuenta fueron salvadas" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 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:329 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:348 +msgid "Wrong password" +msgstr "Contraseña incorrecta" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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 "" + +#: 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 " @@ -284,12 +308,16 @@ msgid "" "domain." msgstr "No se encuentra la cookie CSRF. Esto suele ser debido a un bloqueador de cookies o similar.
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:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Ha fallado la conversión de vídeo" @@ -356,7 +384,7 @@ msgstr "La URI para redireccionar las aplicaciones, este campo es 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:56 msgid "The client {0} has been registered!" msgstr "¡El cliente {0} ha sido registrado!" @@ -375,7 +403,7 @@ msgstr "Tus clientes OAuth" msgid "Add" msgstr "Añadir " -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Archivo inválido para el formato seleccionado." @@ -383,45 +411,45 @@ msgstr "Archivo inválido para el formato seleccionado." msgid "File" msgstr "Archivo" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Debes proporcionar un archivo." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "¡Yuju! ¡Enviado!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "¡Colección \"%s\" añadida!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "¡Verifica tu email!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "cerrar sesión" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "Cuenta de %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 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/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -429,72 +457,25 @@ msgstr "Cambiar la configuración de la cuenta" msgid "Media processing panel" msgstr "Panel de procesamiento de contenido" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" -msgstr "" - #: mediagoblin/templates/mediagoblin/base.html:96 +msgid "Log out" +msgstr "Cerrar sesión" + +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Añadir contenido" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Crear nueva colección" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by MediaGoblin, a GNU project." -msgstr "Funciona con MediaGoblin, un proyecto GNU." - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Publicado bajo la AGPL. Código fuente disponible." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "Imagen de un goblin estresándose" -#: 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 "Hola, ¡bienvenido a este sitio de MediaGoblin!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Este sitio está montado con MediaGoblin, un extraordinario programa libre para alojar, gestionar y compartir contenido multimedia." - -#: 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 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 -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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Crea una cuenta en este sitio\n o\n Instala Mediagoblin en tu propio servidor" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "El contenido más reciente" @@ -600,6 +581,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "Funciona con MediaGoblin, un proyecto GNU." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Publicado bajo la AGPL. Código fuente disponible." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Explorar" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Hola, ¡bienvenido a este sitio de MediaGoblin!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Este sitio está montado con MediaGoblin, un extraordinario programa libre para alojar, gestionar y compartir contenido multimedia." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +msgid "Don't have one yet? It's easy!" +msgstr "¿Aún no tienes una? ¡Es fácil!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -612,13 +640,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Agregar adjunto" @@ -635,12 +663,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -651,7 +689,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,7 +706,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "Borrar mi cuenta" @@ -693,6 +735,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -717,6 +760,7 @@ msgid "" msgstr "Tú puedes obtener un navegador más moderno que \n\tpueda reproducir el audio \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Archivo original" @@ -725,6 +769,7 @@ msgstr "Archivo original" msgid "WebM file (Vorbis codec)" msgstr "Archivo WebM (códec Vorbis)" +#: 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,6 +780,10 @@ msgstr "Archivo WebM (códec Vorbis)" msgid "Image for %(media_title)s" msgstr "Imágenes para %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "Alternar Rotar" @@ -833,7 +882,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 +925,28 @@ msgstr "Contenido de %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "❖ Explorando contenido de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Añadir un comentario" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Añadido en

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1049,7 +1102,7 @@ msgstr "Más viejo" 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." @@ -1079,6 +1132,30 @@ msgid "" " deleted." msgstr "Parece que no hay ninguna página en esta dirección. ¡Lo siento!

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 "" + +#: 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 "Comentario" @@ -1110,73 +1187,77 @@ msgstr "-- Selecciona --" msgid "Include a note" msgstr "Incluir una nota" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "comentó tu publicación" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Ups, tu comentario estaba vacío." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "¡Tu comentario ha sido publicado!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Eliminaste el contenido" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, 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:422 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:430 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 index 4b319ebdbe47cbd07f0c74fe65fdeccf09616a5c..3422ad979e1993332f2f17acc88b7fba2178ed71 100644 GIT binary patch delta 5125 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 I|2pY^0hv}nWdHyG diff --git a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po index 028ab5d4..08e73e1a 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: -# , 2012. +# Numb , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +19,39 @@ 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/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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "نام کاربری" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "گذرواٰژه" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "آدرس ایمیل" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "متاسفانه،ثبتنام به طور موقت غیر فعال است." @@ -59,54 +64,54 @@ msgstr "متاسفانه کاربری با این نام کاربری وجود msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "این کد تاییدیه یا شناسه کاربری صحیح نیست." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "ایمیل تاییدیه باز ارسال شد." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -117,7 +122,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -133,11 +138,11 @@ msgstr "برچسب" msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "" @@ -165,45 +170,45 @@ 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:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "" @@ -228,44 +233,63 @@ msgstr "شما در حال ویرایش نمایه کاربر دیگری هست msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +297,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -345,7 +373,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -364,7 +392,7 @@ msgstr "" msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "فایلی نا معتبر برای نوع رسانه داده شده." @@ -372,45 +400,45 @@ msgstr "فایلی نا معتبر برای نوع رسانه داده شده." msgid "File" msgstr "فایل" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "شما باید فایلی ارايه بدهید." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "هورا!ثبت شد!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -418,72 +446,25 @@ msgstr "" msgid "Media processing panel" msgstr "پنل رسیدگی به رسانه ها" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "" @@ -589,6 +570,53 @@ 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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +629,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -624,12 +652,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +678,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,7 +695,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -682,6 +724,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -706,6 +749,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -714,6 +758,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +769,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -822,7 +871,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 +914,27 @@ msgstr "%(username)s's رسانه های" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1038,7 +1091,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1068,6 +1121,30 @@ msgid "" " 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 "" @@ -1099,73 +1176,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index ada992ce28d1e89631f04800869a27ffc2063092..7bc860a0fd5b08527090f0b09bf279bdfbdfee9f 100644 GIT binary patch delta 5143 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, 2011. -# , 2012. -# , 2011. -# , 2013. -# , 2011. -# Laurent Pointecouteau , 2013. -# , 2011. -# , 2011. -# , 2011. -# Valentin Villenave , 2011. +# ianux , 2011 +# alcazar , 2012 +# chesuidayeur , 2011 +# Bibit , 2013 +# joehillen , 2011 +# hellpe , 2013 +# MarkTraceur , 2011 +# maxineb , 2011 +# joar , 2011 +# Valentin Villenave , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" "Language-Team: French (http://www.transifex.com/projects/p/mediagoblin/language/fr/)\n" "MIME-Version: 1.0\n" @@ -28,34 +28,39 @@ 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/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "" - -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Nom d'utilisateur" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Mot de passe" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Adresse e-mail" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Nom d'utilisateur ou email" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Nom d'utilisateur ou adresse de courriel invalide." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: 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é." @@ -68,54 +73,54 @@ msgstr "Un utilisateur existe déjà avec ce nom, désolé." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "E-mail de vérification renvoyé." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "Nom d'utilisateur introuvable." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -126,7 +131,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -142,11 +147,11 @@ msgstr "Tags" 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:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Légende" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "La légende ne peut pas être laissée vide." @@ -174,45 +179,45 @@ 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:67 -msgid "New password" -msgstr "Nouveau mot de passe" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 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:94 +#: mediagoblin/edit/forms.py:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "Ancien mot de passe." + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nouveau mot de passe" + +#: mediagoblin/edit/views.py:67 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." @@ -237,44 +242,63 @@ msgstr "Vous vous apprêtez à modifier le profil d'un utilisateur. Veuillez pre 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:240 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:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 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:348 +msgid "Wrong password" +msgstr "Mauvais mot de passe" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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 "" + +#: 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 " @@ -282,12 +306,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "L'encodage de la vidéo à échoué" @@ -354,7 +382,7 @@ msgstr "L'URI de redirection pour l'application, ce champ est requis%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 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/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -427,72 +455,25 @@ msgstr "Changer les paramètres du compte" msgid "Media processing panel" msgstr "Panneau pour le traitement des médias" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Ajouter des médias" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Disponible sous la licence AGPL. Code source disponible." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Ce site fait tourner MediaGoblin, 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Créez un compte sur ce site\n ou\n Déployez MediaGoblin sur votre propre serveur" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Tout derniers media" @@ -598,6 +579,53 @@ 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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Disponible sous la licence AGPL. Code source disponible." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Explorer" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +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 MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Ce site fait tourner MediaGoblin, un logiciel d'hébergement de média extraordinairement génial." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +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:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -610,13 +638,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Ajouter une pièce jointe" @@ -633,12 +661,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +msgstr "" + #: mediagoblin/templates/mediagoblin/edit/delete_account.html:28 #, python-format msgid "Really delete user '%(user_name)s' and all related media/comments?" @@ -649,7 +687,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 "Supprimer définitivement" @@ -666,7 +704,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -691,6 +733,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -715,6 +758,7 @@ msgid "" msgstr "Vous pouvez obtenir un navigateur à jour capable de lire cette vidéo sur \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Fichier original" @@ -723,6 +767,7 @@ msgstr "Fichier original" msgid "WebM file (Vorbis codec)" msgstr "fichier WebM (codec Vorbis)" +#: 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,6 +778,10 @@ msgstr "fichier WebM (codec Vorbis)" msgid "Image for %(media_title)s" msgstr "Image de %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -831,7 +880,7 @@ 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" @@ -874,24 +923,28 @@ msgstr "Médias de %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "❖ Parcourir les médias de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Ajouter un commentaire" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Ajouté le

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1047,7 +1100,7 @@ msgstr "le plus vieux" 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." @@ -1077,6 +1130,30 @@ msgid "" " deleted." msgstr "Il ne semble pas y avoir de page à cette adresse. Désolé !

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 "" + +#: 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 "" @@ -1108,73 +1185,77 @@ msgstr "-- Sélectionner --" msgid "Include a note" msgstr "Inclure une note" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "a commenté votre post" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Oups, votre commentaire était vide." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Votre commentaire a été posté !" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Vous avez supprimé le media." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, 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:422 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:430 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 index ce2963f7bfadb0b939456e334a6b9f291235bdd0..e2c22c79ff430543b57690d178d3c67d89f72250 100644 GIT binary patch delta 6868 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 Rrk^@r{!1rf|AT+)e*+NuH)H?+ delta 4782 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 PA|tx{q8{40=&An#XM{sb diff --git a/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po index 12d932c8..0cef1736 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: -# , 2012. -# Isratine Citizen , 2012. +# GenghisKhan , 2013 +# GenghisKhan , 2012 +# GenghisKhan , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +21,39 @@ 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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "שם משתמש" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "סיסמה" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "כתובת דוא״ל" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "שם משתמש או דוא״ל" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "שם משתמש או דוא״ל שגוי." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "שדה זה לא לוקח כתובות דוא״ל." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "שדה זה מצריך כתובת דוא״ל." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "צר לי, רישום הינו מנוטרל על שרת זה." @@ -60,54 +66,54 @@ msgstr "צר לי, משתמש עם שם זה כבר קיים." msgid "Sorry, a user with that email address already exists." msgstr "צר לי, משתמש עם דוא״ל זה כבר קיים." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "מפתח האימות או זהות משתמש הינם שגויים" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "כבר אימתת את כתובת הדוא״ל שלך!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "שלח שוב את דוא״ל האימות שלך." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 msgid "" "If that email address (case sensitive!) is registered an email has been sent" " with instructions on how to change your password." -msgstr "" +msgstr "במידה וכתובת הדוא״ל הזו (תלוי רישיות!) רשומה דוא״ל נשלח עם הוראות בנוגע לכיצד לשנות את סיסמתך." -#: mediagoblin/auth/views.py:261 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." -msgstr "" +msgstr "לא היה ניתן למצוא מישהו עם שם משתמש זה." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "דוא״ל נשלח בצירוף הוראות בנוגע לכיצד ניתן לשנות את סיסמתך." -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "כעת ביכולתך להתחבר באמצעות סיסמתך החדשה." -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -118,7 +124,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -134,11 +140,11 @@ msgstr "תגיות" msgid "Separate tags by commas." msgstr "הפרד תגיות בעזרת פסיקים." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "חשופית" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "החשופית לא יכולה להיות ריקה" @@ -166,45 +172,45 @@ 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:67 -msgid "New password" -msgstr "סיסמה חדשה" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" -msgstr "" +msgstr "עדיפות רשיון" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." -msgstr "" +msgstr "זה יהיה הרשיוןן המשתמט (ברירת מחדל) שלך בטופסי העלאה." -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "שלח לי דוא״ל כאשר אחרים מגיבים על המדיה שלי" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "הכותרת לא יכולה להיות ריקה" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "תיאור אוסף זה" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "סיסמה ישנה" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "הזן את סיסמתך הישנה כדי להוכיח שאתה הבעלים של חשבון זה." + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "סיסמה חדשה" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "רשומה עם חשופית זו כבר קיימת עבור משתמש זה." @@ -219,7 +225,7 @@ msgstr "הוספת את התצריף %s!" #: mediagoblin/edit/views.py:182 msgid "You can only edit your own profile." -msgstr "" +msgstr "באפשרותך לערוך רק את הדיוקן שלך." #: mediagoblin/edit/views.py:188 msgid "You are editing a user's profile. Proceed with caution." @@ -229,57 +235,80 @@ msgstr "אתה עורך דיוקן של משתמש. המשך בזהירות." msgid "Profile changes saved" msgstr "שינויי דיוקן נשמרו" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "סיסמה שגויה" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "הגדרות חשבון נשמרו" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "כבר יש לך אוסף שקרוי בשם \"%s\"!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "אוסף עם חשופית זו כבר קיים עבור משתמש זה." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "אתה עורך אוסף של משתמש אחר. המשך בזהירות." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "סיסמה שגויה" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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 "" + +#: 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.
Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "עוגיית CSRF לא נוכחת. זה קרוב לוודאי נובע משום חוסם עוגייה או משהו בסגנון.
הבטח קביעה של עוגיות עבור תחום זה." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "צר לי, אינני תומך בטיפוס קובץ זה :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "המרת וידאו נכשלה" @@ -316,7 +345,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,17 +375,17 @@ msgstr "" msgid "This field is required for public clients" msgstr "שדה זה הינו דרוש עבור לקוחות פומביים" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 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/templates/mediagoblin/submit/collection.html:30 @@ -365,7 +394,7 @@ msgstr "" msgid "Add" msgstr "הוסף" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "ניתן קובץ שגוי עבור טיפוס מדיה." @@ -373,45 +402,45 @@ msgstr "ניתן קובץ שגוי עבור טיפוס מדיה." msgid "File" msgstr "קובץ" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "עליך לספק קובץ." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "הידד! נשלח!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "אוסף \"%s\" התווסף!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "אמת את הדוא״ל שלך!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "התנתקות" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "החשבון של %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "שנה הגדרות חשבון" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -419,72 +448,25 @@ msgstr "שנה הגדרות חשבון" msgid "Media processing panel" msgstr "לוח עיבוד מדיה" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" -msgstr "" - #: mediagoblin/templates/mediagoblin/base.html:96 +msgid "Log out" +msgstr "התנתקות" + +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "הוספת מדיה" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "משוחרר תחת הרשיון AGPL. קוד מקור זמין." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 זה!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "אתר זה מריץ MediaGoblin, חתיכת תוכנת אירוח מדיה יוצאת מן הכלל." - -#: 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." - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "יצירת חשבון אצל אתר זה\n או\n להתקין את MediaGoblin על שרתך" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "המדיה האחרונה ביותר" @@ -573,11 +555,11 @@ msgstr "שכחת את סיסמתך?" #: mediagoblin/templates/mediagoblin/auth/register.html:28 #: mediagoblin/templates/mediagoblin/auth/register.html:36 msgid "Create an account!" -msgstr "יצירת חשבון!" +msgstr "צור חשבון!" #: mediagoblin/templates/mediagoblin/auth/register.html:40 msgid "Create" -msgstr "יצירה" +msgstr "צור" #: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19 #, python-format @@ -590,6 +572,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "ממונע על ידי MediaGoblin, פרויקט GNU." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "משוחרר תחת הרשיון AGPL. קוד מקור זמין." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "לחקור" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "שלום לך, ברוך בואך אל אתר MediaGoblin זה!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "אתר זה מריץ MediaGoblin, חתיכת תוכנת אירוח מדיה יוצאת מן הכלל." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "אין ברשותך חשבון עדיין? זה קל!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +631,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "הוספת תצריף" @@ -625,23 +654,33 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 "מחק לצמיתות" @@ -658,10 +697,14 @@ msgstr "ערוך %(media_title)s" msgid "Changing %(username)s's account settings" msgstr "שינוי הגדרות חשבון עבור %(username)s" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 -msgid "Delete my account" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 +msgid "Delete my account" +msgstr "מחק את החשבון שלי" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -683,6 +726,7 @@ 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:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -704,9 +748,10 @@ msgid "" "You can get a modern web browser that \n" "\tcan play the audio at \n" "\t http://getfirefox.com!" -msgstr "ביכולתך להשיג דפדפן רשת מודרני שכן \n\tמסוגל לנגן את אודיו זה אצל \n\t http://getfirefox.com!" +msgstr "ביכולתך להשיג דפדפן רשת מודרני \n\tשכן מסוגל לנגן את אודיו זה אצל \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "קובץ מקורי" @@ -715,6 +760,7 @@ msgstr "קובץ מקורי" msgid "WebM file (Vorbis codec)" msgstr "קובץ WebM (קודק Vorbis)" +#: 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,9 +771,13 @@ msgstr "קובץ WebM (קודק Vorbis)" msgid "Image for %(media_title)s" msgstr "תמונה עבור %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" -msgstr "" +msgstr "החלף סיבוב" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 msgid "Perspective" @@ -755,7 +805,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 msgid "Download model" -msgstr "" +msgstr "הורד מודל" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 msgid "File Format" @@ -770,14 +820,14 @@ 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 msgid "" "You can get a modern web browser that \n" " can play this video at \n" " http://getfirefox.com!" -msgstr "" +msgstr "ביכולתך להשיג דפדפן רשת מודרני \n שכן מסוגל לנגן את וידאו זה אצל \n http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/video.html:69 msgid "WebM file (640p; VP8/Vorbis)" @@ -823,19 +873,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 "%(username)s's collections" -msgstr "" +msgstr "אוספים של %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -854,7 +904,7 @@ msgstr "המדיה של %(username)s" msgid "" "%(username)s's media with tag %(tag)s" -msgstr "" +msgstr "מדיה משתמש %(username)s עם תגית %(tag)s" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -866,30 +916,34 @@ msgstr "המדיה של %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "❖ עיון במדיה מאת %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "הוסף תגובה" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "הוסף את תגובה זו" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "אצל" - -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

הוסף בתאריך

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +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 "+" @@ -968,7 +1022,7 @@ msgstr "משתמש זה לא מילא דיוקן (עדיין)." #: mediagoblin/templates/mediagoblin/user_pages/user.html:124 msgid "Browse collections" -msgstr "" +msgstr "עיון באוספים" #: mediagoblin/templates/mediagoblin/user_pages/user.html:137 #, python-format @@ -997,7 +1051,7 @@ 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 @@ -1039,7 +1093,7 @@ msgstr "ישן יותר" msgid "Tagged with" msgstr "מתויגת עם" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "לא היה ניתן לקרוא את קובץ התמונה." @@ -1069,9 +1123,33 @@ msgid "" " 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 "" +msgstr "תגובה" #: mediagoblin/user_pages/forms.py:25 msgid "" @@ -1090,7 +1168,7 @@ msgstr "אני בטוח שברצוני להסיר את פריט זה מן האו #: mediagoblin/user_pages/forms.py:39 msgid "Collection" -msgstr "" +msgstr "אוסף" #: mediagoblin/user_pages/forms.py:40 msgid "-- Select --" @@ -1100,73 +1178,77 @@ msgstr "-- בחר --" msgid "Include a note" msgstr "הכללת פתק" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "הגיב/ה על פרסומך" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "אופס, תגובתך היתה ריקה." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "תגובתך פורסמה!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "אנא בדוק את רשומותיך ונסה שוב." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "עליך לבחור או להוסיף אוסף" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" כבר קיים באוסף \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" התווסף אל האוסף \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "מחקת את מדיה זו." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "מחקת את הפריט מן אוסף זה." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "מחקת את האוסף \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index d9addaa60b99eb33131fbb51b28fa0ac40b62bba..d22f6ee62ee08e646cde4817937d168aaf8876c7 100644 GIT binary patch delta 5140 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 delta 4273 zcmb`|dr*|u8OQO%MY+jUP(jgE1VOnhDvJ=rHG%?CjiU7ut3g?niGmSo5{ho>L^8%$ zQ#Q6`npB!dXh=<4w@qk5($uK64W@OZrdmonO+sp=Ix$ut)cf~ef0QxFbpL>p@D@68e6%t1uo9E- zDU8QX9D_X=isvx^`*9Qw;0JgGXBy)*zm72`j{||R#^m4}T#H+A8oq;1Fv1lqpx-ds zn&21)(Lad{Va{MAUPJ}*F%qk}jbRwUL0y-C95QJb#r&p_Mg|AU?Gp_+g8mce!h=|b zC$Rz}6Rdz&qXzsMYJwvefiIx~`w7P3Pq7VqaU^agJyUQyj%9xHG>vrp9x6rWFdPSv zkGag(-KvZ=W+MGiY{F@%z@JAA+>4sQP-uRH<(5N4Mkpz znxF#tm|DJ6+r9Sj=TJ56L8bN->i#}d;1^MQXb_px1SMMIjYpNT5LKd$s0HsxB>%Kc z8(%K;qgMJ?)WFwKfeoWp6ht&CO(N>}BwU0uFcTYaH@4&ZIB`6a;Z2-@Ylv<(?n7Co;^Lv5N8)XG<53T{Ew@&GcYc?GqAU!qcc4wbPF zQ6>7Deg1}h{`V}|0z@;{YVwe zFe>FS4(q;&sLeV9l}T?N4XyAVREpQ2BCbc>_=w$aL8bfqD4HzY~?AKFrnge~rdk4oprpW)n7}R{AFl#vx=Z^9e4-gfwGH zu^Ja*Cu-MU#X5|bX6^naRN$>xg)ie0{2Ud?5~BMq^P8{G$i`$IW(QWH2HcK(%#*f1 zMq)4nxB`Qx8}k^hLA^OI;R6`XR-cIv;t2c>uE(ROk_It*5XR!&=Rbi)CSEZZ!rX~qVB(mQ5cqG?XhvF>s?5!rYej4ucWbu17+BU z3ow~<&Ka6_SK7}gbQDhi%3`gM) z@B{2YVm9rhm7&aeR4Kh-bFAH8fNV_j4C?2$2Mg$zkd`sH2eoMqV+^)oBzBBcBL zi&}X<>bgN3jl=f&2sE9L)tN}NmCfI=y*n|qK z1y!Oau??R?U6)UKd4-tys7%#hIyU1dJ^vjv!Z~mpwbD0HHS0s(&ZZxm@D?iaUB%YB zyd9(IcVYs*hFbAi`}_dL(*Fn**f8pS5>6czcr;FAelwoNI4r~@tkMarL)G*kDz)E0 z4bXwAZ5K|!*HA0#L)|xoDrJP*ns^p!#S2ky+Im!`_oG)UeVc{`K7)$vENVp;QKh+t zI{tTDgaPxdH&{9DroRi{#~Zj2d+)WLnjD^G_OrPkC*jk`wlY7&J$QKm`G1tg))FhS zKVvfe+o(;GRBEj}8&l}dMb)wzm8r*33pj#GaVIKcucJ!yj(z^Teg5~Taj&9E9k|eI zMV82mT(v7e)vN-Qk#(q4SEDAbLrwH`)Bs0OfxLk#;RV!FaSe6f9n>ZaCv77z9<{(E zREFnxX(-|)s2f+IQth#Q2vxh?*n%&jZpO6rD z(7%o|v1+-UVq8!EAV%U42H`(Y8T=>4U=UHpGQWwZ5r=80)EA%wmtzh#pf=A7s6byr zU3VHo@sFtc|AJ9?3$@9@iCWjE<8&;=mAC`h4(2p^7to02Xg*e<8xJ6FUDJ!r82Ux) z=XM{?pdUfuRib=kKbrfo6<j48>seGrdr(iyAg19REX1j6$p1JR8`fBx;}O&Z zU8ogZK&|95Dy1Rp9PQf87>F&Xf%jt=wqpo(p)z*dw%b1c7S84P88lN;8>TpXfid6r zr4(fQK8^83Ivn*o!yWdY@2dr4{V&EY3rO8Mt9X7*ji<&@Ussev$G)U!M{#O;O?9Iu zqoF8ghyO<0fk6Mhgn~fd2KQ)RxjW9+>~{M;ai8+7NObvI6B9yx?@spk3#M!g^tDg@ zl0P~1aDe|eX)8kfu53?8V0EMK=Xv8MZ1ylu?WX!Vv#oxMqyEc{rq1)QXQ!#(R^#y% zxq5PEWjSX%a_1B}XJ, 2012. -# Emilio Sepúlveda , 2011. +# Aleksandr Brezhnev , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +20,39 @@ msgstr "" "Language: ia\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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Nomine de usator" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Contrasigno" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Adresse de e-posta" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "" @@ -60,54 +65,54 @@ msgstr "" msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -118,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -134,11 +139,11 @@ msgstr "Etiquettas" msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "" @@ -166,45 +171,45 @@ 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:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "" @@ -229,44 +234,63 @@ msgstr "" msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +298,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -346,7 +374,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -365,7 +393,7 @@ msgstr "" msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "" @@ -373,45 +401,45 @@ msgstr "" msgid "File" msgstr "File" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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 "Initiar session" -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -419,72 +447,25 @@ msgstr "" msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "" @@ -590,6 +571,53 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -625,12 +653,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +679,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,7 +696,11 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -683,6 +725,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -707,6 +750,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -715,6 +759,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +770,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -823,7 +872,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 +915,27 @@ msgstr "" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1039,7 +1092,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1069,6 +1122,30 @@ msgid "" " 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 "" @@ -1100,73 +1177,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index 376aace496dfe0c14ea9893225c832736506b508..2fb3a8ce8a51aee4368ec6c0339e90f3a9cdcaed 100644 GIT binary patch delta 6622 zcma*p3v?9qy}R$qT568%6|QDYi`Ou|T1KOS8=G(- z?#VrHXYTszIG6iJaV5Tlt8pT;s7DK><8Px3)Q4B$DU=C5kIY^D6z|8^a1eHnQL2pb z)gBuBRlR)Bw>pXCcosE&h!V1KV+kWpL;6s)Scofe4sO7SxEF85@1QKKbX+jtDwK(A zKpCeUdt~Nm8q(2SC^I{ZWJTSN^1>rnfTvMb=A#UB78ygmi<0|7KIDEGO3s^5Qm`83 z{jDeqxf!L_qT`7_i&F=iT9B))WmCpR5YMWIDyh}H_F6rM_Jhc zlvEzg-Tw}*;JOcI;fMIIICTQ?|8E)(F`YKNjZ&Y9ucL&th*_25B5c5&xCg(EX&l3s zGO@3s?2<=Nit8sRD}N0q;{`0k5*#x@<1Bp`!Aq$d@oAw zk0E`kGbkxMhmx|3C=tn@6ok4EW#Ex0{alao{%Rzss>h%qIlLVu_#u>B{RpM1 zUqlJ%>nJOI6D8F7^ez)0i}L=Y+;w%%29(q^p`>yx?!zwR{T_9RhD=}tqb|W&D4|ZE ztn3)dL{8#8_&iF4HctsczXK%_-6$*n8p`tzphV<2O8?)_-G32f;^(nI_WuVoq=Qeg zH>k|1N^RkK5`GucC^Ije7VP(xC`GgfvpGiz9v=i!sj&DQh z=$j}VKZ_FTmvIQbh7$7MqD1Hd4#Gd7MDpXDd2@s7LX`flMtQGiPOdQzrNf1I1Fpn# zdF)l>v{c~+!iQf(S;51&3SY+2IC);M3mS1O*R41aZ7jxvNO$TRcojZ?=VbpMqah(W zzz366J`z3k5r(mn{5-^)_u?9^8d$Dl;A0wpDN zDBsV=XK@u?g~d&LNBya>G-LudqO8D1%0S(T8c(9E;1!hIzJn9-B1!~?a%{@;<542B z9*4QGq`~4n6e;l!3-C3-)grPT@L= z>+ldthv#r0zJ*d`7f|CzC@C1fJjnGFyou{MD8+jSJ$!aK@gI}N(Yt~l5N_C<7P5l3 zka|%QDRG(Db|l(rAAS#ijCbL!tAmgZTobHFql9(=N(47zDMnFJbT`h#XHX`7p@)Wq z=slDb47xGM)d(EI^#r^Qr=e8&Qk2kd%H6k7a{d)8#^YFkCs3aMK1$?%hVtA+l!#wV zMN0~LrqGa?F2-Wqijy&naxmS6GLdhg6w$+2g?%U;okJPu&nV9iB0uunIF$Fwa?V0F zikgcOxh^b|{hzl!2;mf@e$*l)`szz4p?m>lf^XnG_%TY=-_72WqC0}J!Y5Hy{tA}h zIh6f>5gAAg{Fh*&+$K0!T9*iM zBu}El^~bmrZT8S0%-}6}3g!H$+aBCsm$MbG;{J9Vh8;K-Z^a4dp`@;FJL{W7<19C7 z@ee55V)Bk4v=u11TY(a~-8daxlwx}TYw&TDe*PD$F#qNtg|$d9)L~=|>UVepF54Mw z=P&Ifz6-hW95?o1!7lQMcjIE5U<60#4h(U95Ff(#Foj3jf(R712RWUNveI=p6C)@S z@KEFLu^Ef$Oln|54-E-nHPKMIO8vXW(8OfPE;TeF6*cd6aGUGn5p) zhy(G}-1Yg~_1h@@y^HeR_)+0p17%y4B8Q=x5%ylW=7~|^gcCPh*9`4+t+-i{)J7zs zyxO7TyzdVE_W=o~$Xk2;#>}yj33-_d!w%#ZghFO0Ye_vSWZo`Hvd$dJjC_X@>J4vY$IE0 zey_KG?mgbLl8XL9^Ny8FAHFW(GCRZY`yw)i)2O|(CFO-G=*C;vP~$Z=%;8_%FiliU zN5@Sk>hkILc@GYol6k+u%U|ANy1NbSKc4I#ie{beQJ4jO%%Ty zqxz>`@j_F!)L)$c^SqvxXu|I^`g>|_*|=OMQ7e{k{63~3`C=O0z!iTi z^*u_*mEiO*BPaknn38wxN~=~9n~d%zok@y|7)Df!6c~q@Ef=e7J3A@WB2&};smzI$ z6Y^FqA!0Eq%5lwX5)DVMZ%T30tn~j)<{wK@QEEM@`K+_`gH?wHZ&t?pNs|XtvQgPm-mW!^mu$8i)-2U$N;dk}C>u>S{?1_MPnUSh z3`sR_RvX#cmb$T=%=tB2^9ovwF4LR0c7JKhXPoJ0*1nrJp(WusX->+2bhLYqtbd`w zKiWmX#t9DDiKp!TB8aE$P#Z}IDz1ykb7Y+6*&?0&<1O1zHZ*8vAN5bzq0Gx0A_e7a z@?_HD$H1x?7ZGa;WkN!?|SrT*+c z*LsJiw~zGB>7m}i8N)KSZXS@=oI6wcUrbVmv2cXov7x0@=!g*_q&s^qbV+@6#OUAP zr>`>`W$!<>JTEP!s^tritHLLyJS=v7y(Y$!&5fUVkZsa7sax*=(_0fFq zo$Xh9@7#3lT;hFw3O_Rsy~dqa#_J=x!P$3M<_+9d_xnpQOTJMW)zgMIn8KlJ{8 kIgX{wScuQR`KABtA9_cDQ^kwgJSkt?7)jwqla3MeR#AwW@7L=qeVBfY{AuEM!=AC``KTb9_= zl;xhB9H%L(v4`5CZZ+nr#=6>!j;_X@lR4I!%%-u&XpXg3wPwCQ&YhY6hJ}3gKKGox zf4|?}`&=)dbPR+Y!E=ex_bYxr=U*ECHpNKqe?MnODwR(6FPMqnVF8X$Q0iK&$8q>G zOv1-;EWU)p@GW%US&YYX_%U9@BBg@rjZsP!b0KQ9QZsN4wqZBsVi>nG!bL2l?;B%J za1e*kKZ*>Y{(vL!eUv~xMPgOo<8X}QqTJ_1E~y+G$^5E}#uP3rjC|n3Yv^ys61*Gh z@F*_A5l%bc>rn>02W5hXFb7lz~s8O!yWum%4xw;P;WwN2Dl45mge(eK{D6rcp{m zBCkZ5U=i}G-29QX-5R<6Aj+D)gi_jLD9^u*68QTld*}i(ry7!Kk2fA=Da%lnXf;a0 zeW}!+w%W~~5)7ea`gfFpFQWwZ4N68sh(?ws73F#+F2FpThCbYk59527F`mirD&}D; z(apkbD4Y3k8ugz;;|v$J;25_02Hc6vsp2Vz?EV~-O*0QA^XqXUcA>20UC5m3X_N$x zqm=kGO2y8jEYTN{&#y#2|2{}V22LOxS?h@?k(KdB)~*d@&DNn*WHU;sx1vnE17)IT zQJz1B63AI(71TEn7R9^(LG~|8bNGy^V!({=cHp#)S#lN_F5SluSRu zX#5-*OI^an=*&^77F{?WA4l2sU!sL^x%Tegh!XftY{LE6fd4`Xq=D%6GQau>jp>-q zVK%THWx!tKSKS%$IV1*k4x2H0s#3RNE6SVm46edhwt5k+!)x%@cq2ZBvZOIQc&(M zL1I-+`P6?ojV)ZL!?$rRrc;jD=)x-8jpcX-H{n>K*oGQON~IRqOH_*s=(}+zK7%IC zE4264Qz#WZfpS`|6jFbdO~p~KGAu&Lq!+nI^`lI12ov!<%4zuqrKHZ8_P~COqW^Q0 zfq#L+@oAKb973tsk%+HHK0g_x@gqKX7xy?g7QCK#S*d|yrP!D1BuXHca3M}Cv3GAT zN}zWjuMo8tvJ_y&H7A7Ck-psWm~qUR{Zlqy(8Lw3J~vL?szQAW6ei|Ic= zS!B)5V=OvYhXjmAC#FR#!X)~2I1<}&Joexiyd!e`S13!cACu+$ze7Vx^93%!uW>C_ zS15H89>7M-piCpsgQIaXN{M%%lz2DF679v^_#8?F8Y=Bf+i(K?dypcl0gRXP{|ODr z>@sHH4=4ksU2A7P33t)2Mv45-D5oW=%3g{%luG18`V}Y%wV(vrj-$|na{X46@%u3~ zNaG$FWAO=;0DgzE`_G{~IJVj@VJ;4(Uyd?x4UWfVl;`_U0^E+gQq(gj6P-ahU4KQ{ zQ+YM^i>MKUGT=irB(i-do9F-<_##S)&!DXNd0c^4un-$Ls~WdrvV$PzDRndb>9uwO z`;b*o=THJmn@<&SK5oG~=2QPWX~ZnBOSuyzqk||VJ&q~(Ax^|^QPwVvbmUlGhZ6W^ zl(oMNC4pTLAH^8@1DKA7P!f3;9rc$FYE>j2a4g3U)@p(R+ zDI;8@VQ?XHxxGuPu!R0v%*MTF;_q=6<}-RN9z`$4w%A{{n{g=p0lWo&i?T!oWFglV zM_h(+^jk4SGB9b#rrLtCHhXXa9!5E4XHiN&ven+KNhnKHgi^8Pn2Reh5x1jk>R+Oa za|mVAoxxQ&yv_cf(pn7iPrb$;Ij89yZaJSTuo54{emslYu;T{%>-aO2HJ#ed#>EDF z6hj!mmK*KNPoXU3-!KIeR@%pQGEyAXypsAGG!AelG(1+t3_5%!KNWqI*^@h6eshYiVn$!+O5$Bnp>596 zDE&k782xE-q8^u0rFW!!7uuQX9H##`!3>pVt&Y+UPihaPXW#D#{VAt8CR8%rjEQpj z^{d4xX=_a8aCdkt)#K?hJORJ5%$rTG^7M3?x}xNz!kPI6vy8$yWd*bH3rY$KVjGv{ zFEiJ>eQuAHKaW7ljG_X$iQi(QprEWkPnlge+U;Apu*s;XudnKHPxpAcDnqZ&Ug?l* zhx%0Q8q2M#N}bv&4a}|yA9fjjcaPx;4|KV#E+f3x2)|r`6 zFwF3P%P!Qia(}=G^!0JO+p-MP-Q~87UYED4*Bu_{30N*~_?5Nc5cP9ass@kWWp%nD zlLWl_(wq#PnHZ-Xi5WVfG*;h`n4t5^Xa2YUT4M2J>RuDx=l2`y8L{mDti#UoT~WHw znKZJ=v^oREU^tRwlQS>msXXb>C&nJs@ztyK?bRh?Jv}{UhhNHWskwHCV(PD|jhMNf z-d@x4>xP==b!O^RJ#+5z-tgYRPW|A5hbGmhIrOFp zsquB;ec=J4yC>jxdG$}1+^e%1n)Uju?b@-lQcs&WH+0+57Ki?@u|Kr!x-T61-lh}! zrrgfZv1T(`2lJ-t=GNKzt-KulV(XS@7t5$`%`!r5ZAlKjD!)X(u;SU!#v6(qI&(%w z=%e=iQQ9aPrn3t(^{a&|b(*VM*B4C+-R%lS>APnY>Bi37#8ywhYb>n}_`8jc9yfLI z>H9iQMR%`d?Ay(0xof=PC;ficdeiL>_)YgZON9^n2lG=__+_uxt<0WIuUluVY5q6o CH1PQV diff --git a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po index 1b298a64..81ca3838 100644 --- a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po @@ -3,15 +3,16 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# , 2012. +# tryggvib , 2012 +# tryggvib , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +20,39 @@ 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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Notandanafn" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Lykilorð" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Netfang" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Notandanafn eða netfang" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Ógilt notandanafn eða netfang" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Þessi reitur tekur ekki við netföngum." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "í þennan reit verður að slá inn netfang." + #: 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." @@ -59,54 +65,54 @@ msgstr "Því miður er nú þegar til notandi með þetta nafn." 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:182 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:188 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:206 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:214 msgid "You've already verified your email address!" msgstr "Þú hefur staðfest netfangið þitt!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "Endursendi staðfestingartölvupóst" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 msgid "" "If that email address (case sensitive!) is registered an email has been sent" " with instructions on how to change your password." -msgstr "" +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/auth/views.py:261 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." -msgstr "" +msgstr "Gat ekki fundið neinn með þetta notandanafn." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -117,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -133,11 +139,11 @@ msgstr "Efnisorð" 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:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Vefslóðarormur" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Vefslóðarormurinn getur ekki verið tómur" @@ -165,45 +171,45 @@ 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:67 -msgid "New password" -msgstr "Nýtt lykilorð" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" -msgstr "" +msgstr "Leyfiskjörstilling" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." -msgstr "" +msgstr "Þetta verður sjálfgefna leyfið þegar þú vilt hlaða upp efni." -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 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:94 +#: mediagoblin/edit/forms.py:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "Gamla lykilorðið" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nýtt lykilorð" + +#: mediagoblin/edit/views.py:67 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." @@ -218,7 +224,7 @@ msgstr "Þú bættir við viðhenginu %s!" #: mediagoblin/edit/views.py:182 msgid "You can only edit your own profile." -msgstr "" +msgstr "Þú getur bara breytt þinni eigin kenniskrá." #: mediagoblin/edit/views.py:188 msgid "You are editing a user's profile. Proceed with caution." @@ -228,57 +234,80 @@ msgstr "Þú ert að breyta kenniskrá notanda. Farðu mjög varlega." 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:240 msgid "Account settings saved" msgstr "Aðgangsstillingar vistaðar" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 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:329 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:348 +msgid "Wrong password" +msgstr "Vitlaust lykilorð" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: mediagoblin/gmg_commands/assetlink.py:60 msgid "Cannot link theme... no theme set\n" msgstr "Get ekki hlekkjað í þ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" +#: 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.
Make sure to permit the settings of cookies for this " "domain." -msgstr "" +msgstr "CSRF smygildi ekki til staðar. Þetta er líklegast orsakað af smygildishindrara eða einhverju þess háttar.
Athugaðu hvort þú leyfir ekki alveg örugglega smygildi fyrir þetta lén." -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Myndbandsþverkótun mistókst" @@ -345,17 +374,17 @@ 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:56 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/templates/mediagoblin/submit/collection.html:30 @@ -364,7 +393,7 @@ msgstr "" msgid "Add" msgstr "Bæta við" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Ógild skrá gefin fyrir þessa margmiðlunartegund." @@ -372,45 +401,45 @@ msgstr "Ógild skrá gefin fyrir þessa margmiðlunartegund." msgid "File" msgstr "Skrá" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Þú verður að gefa upp skrá." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Jibbí jei! Það tókst að senda inn!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "Albúmið \"%s\" var búið til!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Staðfestu netfangið þitt!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "útskrá" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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" +msgstr "Innskrá" -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:82 #, python-format msgid "%(user_name)s's account" -msgstr "Notandaaðgangur %(user_name)s" +msgstr "Notandaaðgangur: %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Breyta stillingum notandaaðgangs" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -418,72 +447,25 @@ msgstr "Breyta stillingum notandaaðgangs" msgid "Media processing panel" msgstr "Margmiðlunarvinnsluskiki" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" -msgstr "" - #: mediagoblin/templates/mediagoblin/base.html:96 +msgid "Log out" +msgstr "Skrá út" + +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Senda inn efni" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Gefið út undir AGPL. Frumkóti aðgengilegur." - #: 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/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Þetta vefsvæði keyrira á MediaGoblin 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Búa til aðgang á þessari síðu\n eða\n Settu upp þinn eigin margmiðlunarþjón" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Nýlegt efni" @@ -589,6 +571,53 @@ 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 MediaGoblin, a GNU project." +msgstr "Keyrt af MediaGoblin, sem er GNU verkefni." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Gefið út undir AGPL. Frumkóti aðgengilegur." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Skoða" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +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 MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Þetta vefsvæði keyrir á MediaGoblin sem er ótrúlega frábær hugbúnaður til að geyma margmiðlunarefni." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +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:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Bæta við viðhengi" @@ -624,23 +653,33 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 "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,10 +696,14 @@ 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 -msgid "Delete my account" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 +msgid "Delete my account" +msgstr "Eyða aðganginum mínum" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -682,6 +725,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -706,6 +750,7 @@ msgid "" msgstr "Þú getur náð í nýlegan vafra sem \n\tgetur spilað hljóðskrár á \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Upphaflega skráin" @@ -714,6 +759,7 @@ msgstr "Upphaflega skráin" msgid "WebM file (Vorbis codec)" msgstr "WebM skrá (Vorbis víxlþjöppun)" +#: 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,6 +770,10 @@ 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/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "Stilla snúning af eða á" @@ -769,14 +819,14 @@ 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 myndband ekki virka því\n vafrinn þinn styður ekki HTML5 \n myndbönd." #: mediagoblin/templates/mediagoblin/media_displays/video.html:47 msgid "" "You can get a modern web browser that \n" " can play this video at \n" " http://getfirefox.com!" -msgstr "" +msgstr "Þú getur náð í nýlegan vafra sem \n sem getur spilað myndbandið á \n http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/video.html:69 msgid "WebM file (640p; VP8/Vorbis)" @@ -822,19 +872,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 "%(username)s's collections" -msgstr "" +msgstr "Albúm sem %(username)s á" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -853,7 +903,7 @@ msgstr "Efni sem %(username)s á" msgid "" "%(username)s's media with tag %(tag)s" -msgstr "" +msgstr "Efni sem %(username)s á og er merkt með %(tag)s" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -865,30 +915,34 @@ msgstr "Efni sem %(username)s á" msgid "❖ Browsing media by %(username)s" msgstr "❖ Skoða efnið sem %(username)s setti inn" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Bæta við athugasemd" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Bætt við:

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +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 "Setja '%(media_title)s' í albúm" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" @@ -967,7 +1021,7 @@ msgstr "Þessi notandi hefur ekki fyllt inn í upplýsingar um sig (ennþá)." #: mediagoblin/templates/mediagoblin/user_pages/user.html:124 msgid "Browse collections" -msgstr "" +msgstr "Skoða albúm" #: mediagoblin/templates/mediagoblin/user_pages/user.html:137 #, python-format @@ -992,11 +1046,11 @@ 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 @@ -1038,7 +1092,7 @@ msgstr "eldri" 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." @@ -1068,9 +1122,33 @@ msgid "" " deleted." msgstr "Því miður! Það virðist ekki vera nein síða á þessari vefslóð.

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 "" + +#: 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 "Athugasemd" #: mediagoblin/user_pages/forms.py:25 msgid "" @@ -1089,7 +1167,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 +1177,77 @@ msgstr "-- Velja --" msgid "Include a note" msgstr "Bæta við minnispunktum" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "skrifaði athugasemd við færsluna þína" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Obbosí! Athugasemdin þín var innihaldslaus." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Athugasemdin þín var skráð!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "Vinsamlegast kíktu á innsendingarnar þínar og reyndu aftur." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Þú eyddir þessu efni." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Þú eyddir albúminu \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index 62451511186c1535115755ebca74f0ae3749e7c4..62575b62824640850203412533f503ec7a80ca0e 100644 GIT binary patch delta 5234 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 diff --git a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po index e13345a7..c782fc62 100644 --- a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po @@ -3,18 +3,19 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: -# Francesco Apruzzese , 2012. -# , 2011. -# , 2011. -# , 2012. +# Francesco Apruzzese , 2012 +# gdb , 2013 +# pikappa469 , 2011 +# nunni , 2011 +# Damtux , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +23,39 @@ 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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Nome utente" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Password" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Indirizzo email" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Nome utente o indirizzo email" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Spiacente, la registrazione è disabilitata su questa istanza." @@ -62,54 +68,54 @@ msgstr "Spiacente, esiste già un utente con quel nome." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "Rispedisci email di verifica" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -120,7 +126,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -136,11 +142,11 @@ msgstr "Tags" msgid "Separate tags by commas." msgstr "Separa le tags con la virgola." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "" @@ -168,45 +174,45 @@ 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:67 -msgid "New password" -msgstr "Nuova password" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "Inviami messaggi email quando altre persone commentano i miei files multimediali" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "Password vecchia" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nuova password" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "" @@ -231,44 +237,63 @@ msgstr "Stai modificando il profilo di un utente. Procedi con attenzione." 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:240 msgid "Account settings saved" msgstr "Impostazioni del profilo salvate" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "Password errata" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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 " @@ -276,12 +301,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Transcodifica video fallita" @@ -348,7 +377,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -367,7 +396,7 @@ msgstr "" msgid "Add" msgstr "Aggiungi" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "File non valido per il tipo di file multimediale indicato." @@ -375,45 +404,45 @@ msgstr "File non valido per il tipo di file multimediale indicato." msgid "File" msgstr "File" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Devi specificare un file." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Evviva! Caricato!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Verifica la tua email!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 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/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -421,72 +450,25 @@ msgstr "Cambia le impostazioni dell'account" msgid "Media processing panel" msgstr "Pannello di elaborazione files multimediali" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Aggiungi files multimediali" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Rilasciato con licenza AGPL. Codice sorgente disponibile." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Esplora" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Ciao, benvenuto in questo sito MediaGoblin!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Questo sito sta utilizzando Mediagoblin, un ottimo programma per caricare e condividere files multimediali." - -#: 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 "Per aggiungere i tuoi file multimediali, scrivere commenti e altro puoi accedere con il tuo account MediaGoblin." - -#: mediagoblin/templates/mediagoblin/root.html:38 -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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Crea un account in questo sito\n oppure\n Installa MediaGoblin sul tuo server" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Files multimediali più recenti" @@ -592,6 +574,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Rilasciato con licenza AGPL. Codice sorgente disponibile." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Esplora" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Ciao, benvenuto in questo sito MediaGoblin!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Questo sito sta utilizzando Mediagoblin, un ottimo programma per caricare e condividere files multimediali." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +msgid "Don't have one yet? It's easy!" +msgstr "Non ne hai già uno? E' semplice!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -604,13 +633,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Aggiungi allegato" @@ -627,12 +656,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +682,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 "Elimina definitivamente" @@ -660,7 +699,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -685,6 +728,7 @@ msgstr "File taggato 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -709,6 +753,7 @@ msgid "" msgstr "Puoi scaricare un browser web moderno,\n\t in grado di leggere questo file audio, qui \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "File originario" @@ -717,6 +762,7 @@ msgstr "File originario" msgid "WebM file (Vorbis codec)" msgstr "File WebM (codec Vorbis)" +#: 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,6 +773,10 @@ msgstr "File WebM (codec Vorbis)" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -753,7 +803,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 msgid "WebGL" -msgstr "" +msgstr "WebGL" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 msgid "Download model" @@ -825,7 +875,7 @@ msgstr "Vuoi davvero eliminare %(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 "" @@ -868,24 +918,28 @@ msgstr "Files multimediali di %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "❖ Stai guardando i files multimediali di %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Aggiungi un commento" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Aggiunto il

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1041,7 +1095,7 @@ msgstr "più vecchio" 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." @@ -1071,6 +1125,30 @@ msgid "" " 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 "" @@ -1102,73 +1180,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "ha commentato il tuo post" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Oops, il tuo commento era vuoto." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Il tuo commento è stato aggiunto!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "Hai eliminato il file." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo index 1344c9bdf545fe0c3596f79d1127766f03c45f1f..3c82d1ff45089e708fe94b0fdaef27525257353a 100644 GIT binary patch delta 5189 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 delta 4269 zcma*odr*|u8OQOn3krfDqJYS41-U3e7Z4OgTnI)4f_O{8)C?#aB|#uU(uAVxIHOLQ zDh+QPOK)Dr#N2e$tr=o$Dy`bY=;WelqOrDBlh&HpHnD0OGxq!Q-I?akFu>=W^S*n| z^E~Ig@BZ_*jxP^6d>5jFw-|mt<1dlFo)Go^|8qXlm?XM?#1#Ar-Iy@Kn3-6EWATSL z8h2wX9>!2SjSf7I!|?)M!mF5PjL*CiWlRAB&XLAU#%Z`1S70Xo4mUExRV3&^jz z!oRz_5@$>@{ZQ=2OjO`IQ4^m;EqEGP%Y2Fo@OI#O#28~Jq8W|4F9UtSG>T{_@>0|S zRmiVt;h*+)U10nds69Q5D(x}U=g*)5KZ`m;pCW6Tpm=+}1k_d*qqb-%D&dZJ>QCGB z^RE#7s7(Kkn)nM;U^h`21rd$5CLT4Og0nFj@4-%7joa}%#i%Q@vREgh1RqQfq zi#`urzaF@L+ebqak02cFbs8$NV*Y9G7Nhp;QB*}%qe{IFwQw(Lp#!MTA43Il9@zzR z6IJpkm;Je9)M3p=Rnk{LLm5s-mAC;FaXadRPX_uMP$ln0?cL9C10F?vu6mrkU=x

Rud;RK#a?(NL*hMuIiRP&a;p%KQsdCc)HO<4LFmC!#9i2{;SC zL%#~2!=0!=E63Z9>tlEi{oSYvoxxl^|No$|n1ONW#w^1gRHlE%VEhc3%lr$gF($*9 zS=fa4;cnEazlLoXo@t-{ZdBlXxBy?qTD*e_q?YJ*u)g^|jY*iq!|cKu)PyUMU-N^2 zzd~X#7jPj4Pc&vNHlW^|=dcmOIO=)$C=S72;zPI#wWUF<9)u(D?(-i*Bb0%$sFJ6l z4pjjvgGzK^6KbJ#sEH4t0v$lz_W_3BHPq*CU?dL9vCr5T)cu7>tY$$D^U z2Jgir$}tt2(1ZOr9nWD8#uCMPw2-7syxZQQSvZ@13-;lD^kPM>eYRdgRrCbvX}O+D z{n<7XPQ8jT50%ME2ziI1KlqDl&ko*pYz8 z1J_UbXw2ZkAMjZRj|HzME%1DSJ@HW_33C}|VoafZdKckn`W?u5GV4)WxCfcWyo$qd z059P&Bxds>Wo0UJ9yOmYdYXOu=c6XtgZjGt0E_4^p)9eu6^G(pjKYH$fyYsSoWV%E zg3A0B>OLp?HVQ|fu4kgQpwJ%onMN8aO&1cR=|-J}{WuT*i+ZkWO6&=Dp%yrZ;rJU= zrf;LR=p*dMt2hGJQ(j&nW(&sQ0A}I4I9$*Fe`tg;FtpUpbR=revM?Fl*o|{hk)J?S z;yNbaR~UnF)KdZEpsssxB+d?uH=y1pt*F2s!(<R|0ih7n`KA# zCMMCph{{m!R~?!}Ov7wU#kn{ZSD_NvgsRjQ48<2v3GEMDev+_j6<{#VMomrh+Kh*{W*8*mG1PZQ_Z3+5qJH`S=pZbl{YdsF})VK07yL-Fw{ zyRto)N#FMq8oKcaD)UpQO#T!YzlB`Y@3-d*FNa5&G z1wN+E{<_UYK4RA6bUcGQFp8JTBs_pFJ^z29p~uKM-+sPR0?xs7#ye3N^y6B*hLf>< zft}Gd%%iWHhC@C+gdWtEZo?qlgE~|DF&baRk*sgt3JiRV%HSI6O&GGsUZ@mxc-l~b zcA@Tj7B%rpI0E-#B))+1Q?ATeJ{4(B?_(!z1X$1&i&c>NT7||18F0(1Z53?N}_PU-lsN*Bh&c zfn3~&THqq8M3LXMGZ}{#{h6p2$!T=rm#B$vpbllk68n7+hpJdgz;x90Y@C4wXj0QV zQ(e{r(_XO_M8#R|qBQGH)W#5(t9@0N%jLgTG|XZ3MSIg%E;H+!31?QJEK>2Og$ zB^{;dS5_9#__H5-t6>$ zJ)_I{&3ygkWkVhQy7E_)Y_oq;b%)b();9Xr)xPbpj?}sQ&(xg=@h`7W4*izNR{amU C4>|Jy diff --git a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po index 008a6d27..97d68127 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: -# , 2011. -# , 2013. +# Avery , 2011 +# parlegon , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +20,39 @@ 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/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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "ユーザネーム" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "パスワード" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "メールアドレス" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "申し訳ありませんが、このインスタンスで登録は無効になっています。" @@ -60,54 +65,54 @@ msgstr "申し訳ありませんが、その名前を持つユーザーがすで msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "検証キーまたはユーザーIDが間違っています" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "検証メールを再送しました。" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -118,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -134,11 +139,11 @@ msgstr "タグ" msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "スラグ" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "スラグは必要です。" @@ -166,45 +171,45 @@ 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:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "そのスラグを持つエントリは、このユーザーは既に存在します。" @@ -229,44 +234,63 @@ msgstr "あなたは、他のユーザーのプロファイルを編集してい msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +298,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -346,7 +374,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -365,7 +393,7 @@ msgstr "" msgid "Add" msgstr "追加" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "" @@ -373,45 +401,45 @@ msgstr "" msgid "File" msgstr "ファイル" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "ファイルを提供する必要があります。" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "投稿終了!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -419,72 +447,25 @@ msgstr "" msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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サイトへようこそ!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "" @@ -590,6 +571,53 @@ 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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "こんにちは、このMediaGoblinサイトへようこそ!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -625,12 +653,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +679,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,7 +696,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -683,6 +725,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -707,6 +750,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -715,6 +759,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +770,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -823,7 +872,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 +915,27 @@ msgstr "%(username)sさんのコンテンツ" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1039,7 +1092,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1069,6 +1122,30 @@ msgid "" " 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 "" @@ -1100,73 +1177,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index 69bf72bc8122ed635d411ae889c0637ac4a4df0c..7d37ab7c9c3ac463f56729f1eb8f1d0e56dbe00e 100644 GIT binary patch delta 5269 zcmb8x3vg7`9mnyLkdP30L>}QyZUO{?kOvS9L;^89Vj?6JML_{K$qg*o?2Wsd#3*ES zBtTmg>IxD;i&aMO1vN5)FQ(Ok(psuwTeV`L47N3`t(6u>vHkvXueI%Tv}Hm*=bSzF zJpSi@?&jo6ac}=5E_$MW!WP57&-p)s|Gkq{`|{ss{frq&^*pBI@Kj^+un1>i0Mqa> z9ELCAKs@2K{{=N<%7wVr+8| z$Kx@y@Ej^+Lx&JX%tFR6`Iv-dI2EgK6t?3{_z-Gi=|kNKFGDS)3N=p+Mz!)*3L5BJ zsFmG?oQml{J@6!$YXEd><8wv&bA~)NuDG3Q-GoPy@H17PbbpvyG^uyx(ho2VJi;iLoMt(s9W+VD!E=k?fhLF zja`_Dsg@h5DX0xBj8agD7o$SvM;$>3)u9#j`K_pd??#>dZe&bz2z7+-p^ofNsEEX8 zxS>u$O*{}a&c&$b%aNd(sE>lqa1AQtTTm;05Or2ZP+5H(719%^ot{R8I-b$B@FA$@ zGrW4PXCdlnN>E3+0M}zP@_f{sr=SH4VAe}0p!)AXMPv_Z{Aa!PM@I3~xY1;7v@xlgJ*-8LVJ_lfvk8aWT%r9jNQ^8w{c@v2KZj z+Q|l7ggbE|evDdB=>*;(*oZmUpG>x}1T|hY($z#g_h6LGnKvk0iJ#ytxRBBG3O64XX2bBMo1VHFLU@SB*3 z2T?0Nyi<2jN4g36ji2KtSvroR zUXB_dgyk4T3yc6JI`w28aS{r;be_fvlfhhhy6jl{L6quY*3#v?cy-$WhRCum`2 zg&XnGCENki{0PE|U!3j8R zv75ac9mV1JJ5&-TE^{N3ifPm*p$4AgwO3;v^(e9jvk%E@ld|0XlkRFH zSY|Kk2z#y|{_0q?bA zmtYaT4>qs_jL&>Qme2BZbpUpZcM;ksO$L% z>WH4iL_Fx#4|yKOEZSd1JvZ!QukZ;f#Ghjo_Nt4$-S??Mbxx?k7m3)lDDZ=@jChfj8)reh3$yd)R>dfIcM}eaf51{h6X#RMTBgt z)*tp&2bk{lG0Tz?=QjBKfzHf{p`_@Nf8CnZ;tN|ft9-$gcC8g|s;RNV;ku?kpw)PT z(d-1ha5&+Jsr9v*I-6F1jT1Dh7|R5lm6p>KF%AA;Q^Yn6PB5~{1nm|(WSl@Pzng*% zotv#X*5J=%6A{M>H3cU!v0YPd>G?W;z&0(mU2j@#U+n0V=kg0CO}^O5pE9Fh>ZH7a zyu6gE%1Kw)&Hk|82~L_r9A{XQ^YW+gS$Ds}83nPYr;Fi-Xz_wCQ}4&Kic>~cGRW7ZUvhbK za@Cx9-RIJ|w)~0sghjq)J2qj#ZRv}?CKVrBa4v4dA}17T<$(WNM#h#^4)1)v@<8&1 zS9#mDxB+g4My@IDmG!@6Xl%bPJF0a2!`;t)5ZhsOZCTfK-&0-BZ~Ka@?ApKM_fJ1( h)Nkjyf6vRWPs@-wwSKeZ4RPwet=1*JSXy<(KLCL3YJmU% delta 4362 zcmaLYdvuLg8prW{l4x!&5fX6;Z$jMCa1s(E5s3y7_gh^mh~^+Ji4l5Hb&LjUFiplQ zMF&;GQgJCxwP9kd8cfZw){Mb)F(%6lt&SYDU4}m}=KJ%WnfY(BPR?iV{l4$s&wlpa z=e>T>^|!MwZ$orQjp5JFe+T|ogsS$xzZ=bsiKqHk?1WFyjqO_)GYCgwJKTt^aUaHF zJ%-_Bbm0wbiVb)R8!^ooulYliG3hh}wKS$T_Qz>B54+(RTt^R$IDmRZD`$X17)<>v z(uFyX&F~s3kUL1M<|&3_B#pW+25B-~u{q(X>Y0*A=}X6b4XGyrY)+y6Ar^Je7UEGCVW5@OkhL12ArxIOXT!Y%oCp(b; z{uHj$uo7Fb)!)WV$e5-n>Co=)irO^!sF_c}&NvsfmK%^U&0*98euql&B~-?4qn7Ai z;QGVB^`~A6>bM2rXstV=BFp4UYc~zGW(!amc^8%H)u@51Py-!9J%0`r$PHu_%wtr_ zqb%pSj;PI=jLM`poq}eVg-Y>MRK(?|2j2?R*P>Ehg<88`;#xe5dTvC5Ghi_eroJ4N z*;A;AJVFH?O4L=@8p(*)?4h7kA3%aN=TJ9(gPQq|sF{S2Z?(sx2JDH-NN&I(IGK7O z?#11xKnuD!$Mq-pGWC6^3|+xgo&N_ErqPg)WX$Wh0yWc{7=nJJFY^PAz?iPa48dX? ziu+Kz{yvsrWH)E`FGmHw2`AtI9F5OWfs7`)j~U;*L!lSObC@k0iRy3>@-gcJeul(g z8gL?p^fYD_PDTB4UdLG&!B$Vh1=s|4;tbq_TGC)f55|`G;{3-@2&17LD&?I~n<^bO zg95a$7&XvpRL93qf!3k!yNaQBANBkrY>we6&K`?H-JgNPY9^$R|49^9(old`@D+?F z9sRHvb8#DH;dNYru|%;3ZDdlWt=n0mAvlbBDQ?1}=)wF{XK&S_GWvVeX?d7R{#iB? zNxm{M4Km*pFdPq~GE#@i*p~r+8@PVa zOJN`v{*0Sl91DJ)l$!nNPO7gUlQ1C}&g(WEwR@MLPE9o`pjy-to=3Vdm#`^b#yfZu ziP@Ydt#oOgpneIxsr{YZKL=SZa~k!!y^jN^zd>5qpXLa@gx4?%Z(=k20bAqqK)p5V zr0a>O>wT~l=3y*OLM_2Ur`>BlprDRxaTFfK>G&K8+Dy;p#e_Dh<3C{}-ay7gj&)_I&G@+-;Y8B4f&{!OfU}wSnswu_g7(sF{BgXnz_oIG3gLav_33drU%gn1@Wl%tEc<4s4FKs2QC= z&E!k$gjcZx{u8x#qVt^B?LgG?9xTKqXyGXwf(__Zhg}9c9Veqwn}!zVpmyy{)PNow zhRZPte}lX6JB)Sl7Ub-1puU@YYrtNN@*2L4n%Gs;@qUOavHwu=zmvijL!I6HD!s>3 zUyNF#_febZBzDI0s3r2Fg)s%rQe~jlJ_j|Saj4@rC2)N27gsR{s&R` zH4WB zOz=`r#HFYQ7o*l}C2A=)pfa%q*WwxMj)fzfKr4{!o2^Jz&0kOhCyaDV$13W>F&wX< zGJFerpx4EjQvk`R2h&ig8XBn2!({3!Fa$rrNIZldJb`<$(`YAvb2x!|_KI)0pG*6V_&>&y=Di6W;D3QIf1l54H%0AX$B+NG*zgMuc3B(%6R8>TZlcWpTH!% zjk+&_uZcJVb((zmF@BHywwX;_d`0K~0tL;u#Uv*sshCIoHB^T?P`mXEYNmroY(DC)b%3N4_OJuGrn0yL7T`%t?gmd=K31b@i{iZ z^r_A<%0m5KOv4C#1C^1VqBiSJ)EXZTv|mOy_3x37Ntotj_8s&Rq&ZK4$ry{ns-Ma? zQ8(73&Ufr|=XHAmb$$mGImhum)bsoBQ+$rf)Tc9?iS(N3WM(od!|PF*J&0P;`!mVE zj$8j(&g-@av#3{LG+sbG*nrh&ik)-+3k;@u43(+RQ7LUe9kU0hR6h>*FI1+Q%r<5$ zMxjYesz|i#ps0iPgs3+5ji}mC%PLgEbUdkWNwb{bicW-z_gp&B?G)}|LTMO5BK|b zR$F&{mHu5dR^z^njrN|qbw{#$7yoC@meshmx^ewxQed~p9Mi*JxxMjNW#is@%fG$y zUd?uEl&7S$cv$)Dg{5Vdzj6=#+^gA2ANI4BHFjLq{GQ~m@$*%8kF2t2ZCt, 2012. +# Jin-hoon Kim , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +19,39 @@ msgstr "" "Language: ko_KR\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." -msgstr "" - -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "사용자 이름" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "비밀번호" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "email 주소" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "사용자 이름 또는 email" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "죄송합니다. 지금은 가입 하실 수 없습니다." @@ -59,54 +64,54 @@ msgstr "죄송합니다. 해당 사용자 이름이 이미 존재 합니다." msgid "Sorry, a user with that email address already exists." msgstr "죄송합니다. 사용자와 해당 이메일은 이미 등록되어 있습니다." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "인증 키 또는 사용자 ID가 올바르지 않습니다." -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "이미 인증받은 email 주소를 가지고 있습니다!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "인증 메일을 다시 보내 주세요." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "비밀번호를 변경하는 방법에 대한 설명서가 메일로 전송 되었습니다." -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "이제 새로운 비밀번호로 로그인 하실 수 있습니다." -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -117,7 +122,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -133,11 +138,11 @@ msgstr "태그" msgid "Separate tags by commas." msgstr "태그는 , 로 구분 됩니다." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "'슬러그'" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "'슬러그'는 공백일 수 없습니다." @@ -165,45 +170,45 @@ 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:67 -msgid "New password" -msgstr "새로운 비밀번호" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "제 미디어에 대한 컨텍을 원한다면, 메일을 보내주세요." -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "제목은 공백일 수 없습니다." -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "모음집에 대한 설명" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "예전 비밀번호" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "계정 확인을 위해, 이전 비밀 번호를 입력해 주세요." + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "새로운 비밀번호" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "해당 유저에 대한 '슬러그'가 이미 존재합니다." @@ -228,44 +233,63 @@ msgstr "사용자의 계정 정보를 수정하고 있습니다. 조심해서 msgid "Profile changes saved" msgstr "계정 정보가 저장 되었습니다." -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "잘못된 비밀번호" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "계정 설정이 저장 되었습니다." -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "\"%s\" 모음집을 이미 가지고 있습니다!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "다른 유저의 모음집을 수정 중 입니다. 주의하세요." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "잘못된 비밀번호" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +297,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "죄송합니다. 해당 타입의 파일은 지원하지 않아요 :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "비디오 변환에 실패 했습니다." @@ -345,7 +373,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "이 항목은 공개 사용자들을 위해 꼭 필요 합니다." -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "사용자 {0}님이 등록 되었습니다!" @@ -364,7 +392,7 @@ msgstr "" msgid "Add" msgstr "추가" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "알수없는 미디어 파일 입니다." @@ -372,45 +400,45 @@ msgstr "알수없는 미디어 파일 입니다." msgid "File" msgstr "파일" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "파일을 등록하셔야 합니다." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "이햐!! 등록했습니다!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "\"%s\" 모음집이 추가되었습니다!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "메일을 확인하세요!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "계정 설정 변경" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -418,72 +446,25 @@ msgstr "계정 설정 변경" msgid "Media processing panel" msgstr "미디어 작업 패널" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "미디어 추가" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Released under the AGPL. Source code available." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "이사이트는 MediaGoblin으로 작동 중입니다. 이는 특이한 미디어 호스팅 소프트웨어중 하나 입니다." - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "사용자 계정 만들기\n 또는\n 서버를 위한 MediaGoblin 설정하기" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "가장 최근에 등록된 미디어" @@ -589,6 +570,53 @@ 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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Released under the AGPL. Source code available." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "탐색" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "안녕하세요! 미디어 고블린 사이트에 온걸 환영 합니다!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "이사이트는 MediaGoblin으로 작동 중입니다. 이는 특이한 미디어 호스팅 소프트웨어중 하나 입니다." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "아직 아무것도 없으시다구요? 매우 쉽습니다!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +629,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "첨부 추가" @@ -624,12 +652,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +678,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,7 +695,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -682,6 +724,7 @@ 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:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -706,6 +749,7 @@ msgid "" msgstr "사운드 파일을 재생 하시려면\n\t이곳에서 최신의 브라우져를 다운받으세요! \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "원본 파일" @@ -714,6 +758,7 @@ msgstr "원본 파일" msgid "WebM file (Vorbis codec)" msgstr "WebM 파일 (Vorbis 코덱)" +#: 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,6 +769,10 @@ msgstr "WebM 파일 (Vorbis 코덱)" msgid "Image for %(media_title)s" msgstr "%(media_title)s 이미지" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -822,7 +871,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 +914,28 @@ msgstr "%(username)s의 미디어" msgid "❖ Browsing media by %(username)s" msgstr "❖ %(username)s의 미디어를 보고 있습니다." -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "덧글 달기" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "덧글 추가" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "에" - -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

부가 기능

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1038,7 +1091,7 @@ msgstr "이전" msgid "Tagged with" msgstr "태그 정보" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "이미지 파일을 읽을 수 없습니다." @@ -1068,6 +1121,30 @@ msgid "" " 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 "" @@ -1099,73 +1176,77 @@ msgstr "-- 선택 --" msgid "Include a note" msgstr "노트 추가" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "게시물에 덧글이 달렸습니다." -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "오우, 댓글이 비었습니다." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "댓글이 등록 되었습니다!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "확인을 하시고 다시 시도하세요." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "모음집을 추가하거나 기존 모음집을 선택하세요." -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "\"%s\" 모음집이 이미 존재 합니다. \"%s\"" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "\"%s\" 모음집을 추가했습니다. \"%s\"" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "미디어를 삭제 했습니다." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "모음집에 있는 항목을 삭제 했습니다." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "\"%s\" 모음집을 삭제하셨습니다." -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index fe96d40e5441640d4c7f563b97e3e98e44b1e35c..4e6e51ce1809030467c75beb68db3412d93469de 100644 GIT binary patch delta 5183 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 delta 4388 zcmaLYdvKK18OQOH3j}f__k>GeNhIN7!V;1|F2(?Xgb)xRNQkIxl9#v=vN0DB3NF$K zRuExWw9V8~bjVOeoRY0mY>}1O;ma4QMcFHi&5qkOlc;Alx)y!r;=bZO_ z&*gc}dH2wD`~wN$FB<;7;C~eV8zNNu`tM?_G3iwQgk$hFx^d(%WA4Wq9D&bc z67I(oJc2{;EQa7kjK%@{3tq)MWBlfWIAaQE2#q&pGET>Od>pg!U3``vu3{1OjzoKa zgBV8rIMRhVi7|K{HId86T+JOEicvJ`zGS4yWMM4hn_>zRXqf9<=)ghLpT$Dlj#YRZ zt1%|oo^Tzi!xvBk{1Bt?HPpo3!UTL9d+-zv#+8I816N}zi9ZpVz*E$3S%}(&2Uuv7_7uecrSL~M%;@Z;pmYJhBt8%E@O82*p1rE zKO05-r&G8o=V1cl;F8@i3;NTxX(YR?L@jSC7isDpW)^qC&kHHSiA9Kz*p^PoO4p5y^tN zg$j9`%YJS&YO_v4MbckDK`Sglg?Jfi#y-@8PdW81sF3eKW@T(1SCn zuSZ4p9n?Z@q9z`}tao4%5)r@IM?s-JfK1k$K;8HmYUS5aD+wpwYEMTEI1v?*a>v=Y zlzKJx;;X2MR^4MC*C+8_>ibaroTmg^Te3F2MhwCbEFpy~6nBTNH9Jox|+H8dQg?k&oHx z_!DFfW&mq3e4;U%a2e{&c>z~oBwIZXSK%PsgOB1qR7%4bJq+XV?)guqFocE?sE}u( zHdO&?1y$%m4{D&zsE+$k6FrQ&??a5hFHz6m#8@1fWACvv)cu9XT+QMf;=hE#(==4! zIh=**gku_dupE1^1TWwQOkoz?7(f;$(q-O3{oG!`BI@mgg?E&B12sTD#^E`~&oGJl zO^n4T@+3!~+9zNlmO1Tr$KG$YQBY`lk;R(>s2qNR3vqm@J=1llfe)fWdlaMa zBx*OGL#60r?7^$3`??7)uMo2X71=&iN>5|7&i@?>ku(e~vqPGM%Go5;-k6GASdW_d zY3KS^m`pvCyvQ_+$6VCJ%AI{y4R{=t(rc*5WmMR|2{rgM_3jGd{~Ze9v+do! z9hIYls0sC>Hq%+m#7n4MJa~?M3W`t>szpWQ5!7>SPWw|%{TbAPo zhPikFc?X%H^Nnf3a%|N3@1+o}3k&QSrl4}2j`V3}AZa(-aWS4n?fUEo?4R2TR7iuU z6ughR?=osLmMpaQ%pQD&`WaM2J08@;$p6a}v>Ezw0$y^AUS$8=7NUpt<*40$6gm2) zgi%)Ddd$N=qH-KtYyUPRVGQ*S48vzo5$wiT+=}UpZ+a-`T>ccbf-|TTT*0Xrv&8Or z25RM%sQa2Q0yknJc02aq-BX0RzaJ;!Uy+YVe8~Q_^`iEl>7yXO!g8Fs)DGddaTE2A zup8^@>`ga-N>TJOV@lDD&A1vn@IxGfbL;JhdQqD;fZB9@$lA>Ldg8Ac=00ry+|I*n z>Kicudr>PrjE#5()p5ac`{#BErckfLNc3R@u6NvwO37A?!kx%F%e;&xV_ZjuD-as@ zMqqJVYT#nr>k%%OuRYS`3O*O#8Zz$jsbw>onye<5ueEeC6)xznw5@F1_$E)MHKC() za$E35!nV+0cXCl^;9seUfy=20fe~rtfgNeLgS&<&4+->-wSq+%4WWU(_dF6zANOKN z@N`yfM6fW|iU{>|296b^jaq3jhPTnzYFd2FE?-xtX|>i`?Z(&AWCcnKk4%}G0nbmH+d%$XUSyrpd)7a?iYVCCS z+FVW6dds!eYUuEGT6$)(M>jixP%wNezfo~|t<2X=l~zN0mv@zGzSZRQRQeiPyshf- z3Cm@9n;E6UYF}fuf8A*yB;kp`Z;E$LB+|7$tJzw^7qM^qKe4YZ*%uo8_k9(ifx7Y> z;$9expAi!h%$nIbByhC4IhZ?dZ)o7`e1EWg!Tylow1tNwf+2NBB0_y_3jCP=1^%0n Q_gY, 2011, 2012. -# , 2012. +# schendje , 2011, 2012 +# mvanderboom , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +20,39 @@ msgstr "" "Language: nl\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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Gebruikersnaam" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Wachtwoord" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "E-mail adres" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Gebruikersnaam of email-adres" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Sorry, registratie is uitgeschakeld op deze instantie." @@ -60,54 +65,54 @@ msgstr "Sorry, er bestaat al een gebruiker met die naam." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "Verificatie e-mail opnieuw opgestuurd." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -118,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -134,11 +139,11 @@ msgstr "Etiket" 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:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Slug" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "De slug kan niet leeg zijn" @@ -166,45 +171,45 @@ 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:67 -msgid "New password" -msgstr "Nieuw wachtwoord" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "Oud wachtwoord" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nieuw wachtwoord" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Er bestaat al een met die slug voor deze gebruiker." @@ -229,44 +234,63 @@ msgstr "U bent een gebruikersprofiel aan het aanpassen. Ga voorzichtig te werk." 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:240 msgid "Account settings saved" msgstr "Accountinstellingen opgeslagen" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "Verkeerd wachtwoord" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +298,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -346,7 +374,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -365,7 +393,7 @@ msgstr "" msgid "Add" msgstr "Voeg toe" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Verkeerd bestandsformaat voor mediatype opgegeven." @@ -373,45 +401,45 @@ msgstr "Verkeerd bestandsformaat voor mediatype opgegeven." msgid "File" msgstr "Bestand" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "U moet een bestand aangeven." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Mooizo! Toegevoegd!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Verifieer je e-mailadres!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Accountinstellingen aanpassen" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -419,72 +447,25 @@ msgstr "Accountinstellingen aanpassen" msgid "Media processing panel" msgstr "Mediaverwerkingspaneel" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Voeg media toe" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Uitgegeven onder de AGPL-licentie. Broncode available." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Deze website draait MediaGoblin, 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." -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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -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" @@ -590,6 +571,53 @@ 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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Uitgegeven onder de AGPL-licentie. Broncode available." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Verkennen" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +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 MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Deze website draait MediaGoblin, een buitengewoon goed stuk software voor mediahosting." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +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:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -625,12 +653,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +679,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,7 +696,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -683,6 +725,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -707,6 +750,7 @@ msgid "" msgstr "U kunt een moderne web-browser die \n\taudio kan afspelen vinden op \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -715,6 +759,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +770,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "Afbeelding voor %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -823,7 +872,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 +915,28 @@ msgstr "Media van %(username)s " msgid "❖ Browsing media by %(username)s" msgstr "❖ Blader door media van %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Geef een reactie" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Toegevoegd op

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1039,7 +1092,7 @@ msgstr "ouder" 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." @@ -1069,6 +1122,30 @@ msgid "" " 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 "" @@ -1100,73 +1177,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Oeps, je bericht was leeg." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Je bericht is geplaatst!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "Je hebt deze media verwijderd." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index f58e6a45afb70117bd19a4d6cc97e5340153f3bf..f9666be3ef7b804db10d01c0ecbf7b37db773c74 100644 GIT binary patch delta 5190 zcma*p3v?9K9mnyTfY}fbLP)}!41u6L5)wjq3W6jM2yY??g1X60k~N#1bRWbmn$;?b zk5s3lf8bR5?L^mr zPhvMbh>T%g#ikoj8f> z_hB`@f(vjMv#7uzD)9GF1MSA1_!HCwpGD?wUckHXC}v<=e`5+6-?Y=K7?9W!9aJw`KXC3MU7LBNzFV#LxFBW z&1^HWE9NfL1G}(0K7(4>0n|VTkul6)QG4&>L)QyYdp;Yr1q)EmuSPB85>%}<49^8iK;6Bt|zJbcbhsYRa*kE@nrl2P5paQp{CUzxiWt&i2d7pRvA)H5lH;%(o zcoh~6A^*Rj@gUQw!wr=BSnNclG>cgk;Q2TOFU5Ae6BF2V^dB`)g2vZ%6I@4kV`8huXqps4e>&DkJH` z-BkNf1LvaROh!Gw078FvolbO3d;seC z;a-2d=M>b|%tmeHBD@~gBhM$zCp0vHevEnnjzgu|L9J{DY9f2_R(uwfp_L=u)UQKj zq7Ak3EvWnNL1knoD*jKs>qk%%KY`tK{y(Cj0H?byP?<%>tfD_0w_^e|^MXrHJE=6M-0D#%D^kw9Zw)@Ft1|`b69 z4r(Pg;0oM^i}3^0gyxLl9fGY`f;m*Og|kud>X2Ja(sL&!S)6&9MlJpmug1kh(<}HO zUWT9I1iY-+t$`F?LjNw*o}a>Qn8B!8VHRd$AJi5M@En6G!t+oISyDp&EgDT+(117M zS-2N9<9*(Ze?TAo4^aU=!QPn7L)wA@)crG%#hW#FA#TKK{5{UWk)@mfY{FT%t(5#v zr*VP{SK?4Ma3kK0B*R!NTYI$-=V2>u#wXFnnsT>x_MlSx66$z;jFf@N;UzK+r=nII zL)FN)QStXBY2?s&3$>CnsMHRra072Z1=@-VydRb7SFr~kMWy@=REFNh4Ez9<$&WqL zCb@kdD&E##B_mnK%Qh@%1#$Dh{LHGR4irElBpwZag24VLld2ShTv1^cU=0?;wH{&s#|2t@qO%o?ijAeG9QgjSgV_){?VV-Qp+4OUmodVaQiY$cv zFphd(+=!aM-ClnWsz~?a06c`Moj1F#v;U`P@D4H=Gu;%8#ytAty?zx^Kc)s%D;toL zX`Vo`YmQ?d%qJZ^aTIFB6R;OfLrrKNCh!vP``=>M@Bia8w4!da+<^z9ilYoIT!%_o zJ1X!d)cv=4{T)cznB6!O|Ah0g8|kue5$d@xYUS%aH)2vLyxqIuUR2R+$G*4=wX&yC z#qul6!oxTWkD~57joO0VyuXXE5EZu?_53naTt6x!ji_3QUBLb;HMeoW!bh+WpF=(H z7V7xChl6k&hj<~*L#^m`)M>Z}m7#5@)AT6n`KM8Pe*n+Jmr(J0S8|lGtTJiLaT*VB zA&A#jxv$c9P$?ZW*PYlB)Lyq@1Rus24xHys>^rF9+KF1(e$+%daX7x`UGG=zem@>F zxL%W_p_DF1rFb1?VjcRh8CBI$9EjJUGIk&8jrU_z(H-{eM8)|FD%J0zR(u*Yp#lm+ znVf){XmSw^1rDMDU5g{|R#dTcU=Q4nO6iNJy+4fF`}eR1c3a@4`fSXkKNz)uk(hig?Z z&)?*Ie=qi={}d|TbJ+F!|5X|VTIt7cIGlTa@-8;fv*cl~}$YGsFLXyEs;9W#kO9&f-^_yiVXpIWzS zXP}N#CF;3rP^tf(=T^+3zYY81E>wn|Mit)?JQv@s^?v^kxX{hORMg&Gj!IE0>P>eG zs>mL~Z2Tei!hM*BFJcb9hGX$VBnf8tO7}0TD5|#hq84@rCt}Ge@~;%tv&>s?Gd_+5 z7r8h78g&{nR=fQ%*hGH~2JryqWAPfd7AjFIu0v%uhRW0y%*7)(2H(Wdn47%VeRa-6 zt#~;yc@swM_0Mq>o%Dw9>7HJ-~*@m8Up8`SPK zu0^GI6RP?*uTA}~_hWetPNc;ji`juoW5E`Cbky=UIwn=tXJBf3pGPyDNS39alrwoj z$M)=kw9QisI(p^=)4K-(cAz7YJ3T$ywh~S}Vzv6C(KaU%C`mn%KQ^^9zklXuS5k-a zFBlUFhMTRzqG;hXt0-#OR|KOm#tH|lVAKjbG0Sg76D_(atHaknBh5D_V*8m@N3Q|- znFU=BH#l)_XTDuwrdtua#aSN=H+9`kv>_e}C5#u0%TCx!hZBvNfIndxY_10Dov>*lmI*nHmJ^Se zmS8v@vrUT=jy0LE-DXFO6AJJd4?Env-fCbD!9o@hbF4@_JdT0w`esYdHv~hrX|wHS zld%1%7s{V%swkc?*(xiaRxz=-w4$^$Yw42W<@WkuH0XqjE6L+DYeH#RIp1~NH--Dg zmhzLe&>xKz*GBx|XviOPBGat;HoLCQj#%e;jah+sG?u6jIq^V=6KU*td*aX1a=)x* zQjbpBni`co`U@qK+Mc~U)nm%RA5DG6tC**zzmt|Xrz?g3TQ)mp6kA>2Xy=N~jYsWB z*sqd2C;EADrH;%fpE$>fhXP$i^Yx1=l`(Vg=QZ`r%(r|amJs8s>T1W_%YBt|yYk(U zJ#TG#_Z9y2cB*;)#RV(AqQrhNzcp>h3MUdtuyJ2nY2`JA8GSGG7HLt{Zq?N;EAox{ sdR3RY>Y|ZrRbrM~S__@VM(h7dD?xo5I~3sa3#Ikdl@&=ne$o7Y0}IzQv;Y7A delta 4349 zcmZ|RdvKK18OQOH3*^QnBqW4O@FfrkmxK)=kz9&F36~^*3dlw3xUer_%VsxCwptKa z#R4-5LV0T|?LdWs2v`PKFTui;a4T(bkl{8kNNJ0vg_KUI16on~{rT=p|7vElpL5Rp zzUMsWIp@5|#|Psc?2n6F%Se3P@YBI>KYo`bsrJ90tKE#rrTPgzgkPZt`*t_x5v<2P zxE6cjPRzzbn2hHz4zFStyoP_pTR6&?h&hvPOeqcVJ&YNNV{k4m!XbDJ*U-Z)ET`U* z=??H~OrU-o>B5}Cu6P+0NIMd%xsNHBMx*Y_LYmBA?8f+}g2GT5CdV$cU?=KpungDX zBs`9_*fq-ycs8oT*H8oe64P)ODzNu30}tXRJdK@kA?eA(M(oA-W&?!+d>fUbvzUt4 zkdOI0U*E1uFJt;sPsXJ<1Qqx;RL7@L1D-?1GM}LWydS&XHOCl|XnLaV8;p@e3gr|O z`B>BdwaCZ#`O@01jJ0n@t?40DYEPh^KaUFhGHMTfhKy+vdb|DgMJ;6oYKi8fCfwAU z{8KiY_$tFFYNj_)9p6C(b`Le91ftQ>^hUKmgcET%j=&aNj&I^6?BAEc@GcI=IYc)a zSD`lZhyBR^7z$TtSb>>r^(D9w8Pjwj9oqeaQJZEwYUZOI^vllgi-=k7| z7L~CZs3rPG?E2@i>-QrR)Nyyh(OM5gMOML=)^09p%@(6FvK*D_m8gN&qXs&Fdj13| zkgLcln0u&{r(5oG{ZX5BI4YBoQVN=3B`U>pP!Wev5B@M#UyVxndeqwe0$1a4)N^$M z+yTA#DD|bN%pOKfL3VLCqwQe5*YdHQ+E* zMyg}h;4JF3xC6JL0-ZF-J+9x!5!830GISn`b^iZJVJ-~=@{L)5%TP1Dj)~ZT^kx2q zb(l5Sm>Trr1l)<*^|vvIX+zxIzZ4btMx2g&a4J4P1u~WBwlcnXfkF}Ha+ocwM|IeU ze9S8`-$i0D*Kh_V4m0LOoP&CEUcqNEm90Js7h@;fg3sV~)RHDJdII*qZ_j@gg=8A~ zpi({%wW&%`Gnj-HdQk(dM0I=s6=*B!z6+Ryw^7gE#cr5V=oW2&DOK+ItwEAug4i9m zV;a7Tn(-0rf~Qb{T)-vR5xc&S^lHE$Y9c>IE$J>y(fPkXK^^@mc0+rt{s41nPa4br z2AGc)hEVr!K+Wupm^)D!dLK2R-(n9ufeQQ*>V49Vsn~)2b^h;B(2dzFuu@xq`B;VO za6YPo#i)*7K+X6i?2E6VX1*IOY(vfXFR1%FRlA!z4f{}^fc5Cbh-R{vf?f#kqc+Wl zsNH@X)xjmyntp<0)!af2P{0Oh!aBT;htQ9kA9dewNt|W&vl)#R`cX^y3O3`B$H;$} zLdkeHvbRy2<``;bS5bj{fdeqD#%(W*IT<_CZlh8fz(jl=mAPf839dqI)^(`AHCs>_ zYpsd6Z=^FcXj65>`~uZc;siIw`SK|cKKp(~0+mYm$lu7P+o{9?aMbwNP+<@Cr z0hCU52d+c~5}86l7XqjUn`0MNp=Poj)zLmwM%pkLPa+4zoWX6_wbsqhKGZQjhkAo1 z)VZlHMT>epK8cO^gwFpF3Mn*XuqD&5A1b8m;#yP&w&Ftk4QeKNQ{1H- zhtsJ)gVlHddAXW@<4PPd)!l@UF3!Uy2%dGp@h`I1-B= zcmLt=Vj=Z|*csbVr{p&3x#3JxnX8UjgId~J%w~KulY%x=01I#pTDT8Acowxp@#IaJ zNk+ZN2B9)nh3Pl}yWlL;gnXEROK~`^L%K2tu?EvfQ$(BR2@0CgPjNJ!L}lPBT#LhI z@NU2lQ1=CAx__Lupz23)5#B*RKK+!tbSF@6(5u)3|AWeCmsxIxM$RJtN>PA@VfYdb z#dk0hFQR6A6Y1M@p6#yjJXA`TpgLTEakv$e@K>me?TNV`m8lO|=2Xja?w4@PgT>{`~sghY!7Xz z8rkIdEAyO=%x=zmm0O}mGY`i_S7nvQJ74$8blQ7mIDK-eo%K0iMK|`&N_PG@z>b#Z z&5w899Q562ZvN|W(T@kuNQ#yf*-7!V>Upb3N;tk4g_CTKrzH=9tv zXFFA8hZdF;dPZBtV=6qO3q55XPwL~-3ZJx}^SAgz!NTzbRbh?t6mwHaVX?<5E~zLf z9`4~MwcgtjE}YTq4YmZl;ZSph^_(4O3gl{U, 2013. -# , 2011-2012. +# velmont , 2013 +# velmont , 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 \n" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" +"Last-Translator: cwebber \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,34 +20,39 @@ msgstr "" "Language: nn_NO\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "Ugyldig brukarnamn eller passord." - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "Dette feltet tek ikkje epostadresser." - -#: mediagoblin/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "Dette feltet krev ei epostadresse." - -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Brukarnamn" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Passord" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Epost" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Brukarnamn eller epost" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Ugyldig brukarnamn eller passord." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Dette feltet tek ikkje epostadresser." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Dette feltet krev ei epostadresse." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Registrering er slege av. Orsak." @@ -60,54 +65,54 @@ msgstr "Ein konto med dette brukarnamnet finst allereide." 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:182 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:188 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:206 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:214 msgid "You've already verified your email address!" msgstr "Du har allereie verifisiert epostadressa." -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "Send ein ny stadfestingsepost." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "Fann ingen med det brukarnamnet." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -118,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -134,11 +139,11 @@ msgstr "Merkelappar" msgid "Separate tags by commas." msgstr "Separer merkelappar med komma." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Nettnamn" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Nettnamnet kan ikkje vera tomt" @@ -166,45 +171,45 @@ 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:67 -msgid "New password" -msgstr "Nytt passord" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "Lisens-val" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "Dette vil vera standardvalet ditt for lisens." -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "Gamalt passort" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nytt passord" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Eit innlegg med denne adressetittelen finst allereie." @@ -229,44 +234,63 @@ msgstr "Trå varsamt, du endrar nokon andre sin profil." 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:240 msgid "Account settings saved" msgstr "Lagra kontoinstellingar" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 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:329 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:348 +msgid "Wrong password" +msgstr "Feil passord" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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 "" + +#: 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,12 +298,16 @@ msgid "" "domain." msgstr "Finn ikkje CSRF-cookien. Dette er truleg grunna ein cookie-blokkar.
\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:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Skjedde noko gale med video transkodinga" @@ -346,7 +374,7 @@ msgstr "Omdirigerings-URI-en for programmene. Denne feltet krevst%(user_name)s's account" msgstr "%(user_name)s sin konto" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Endra kontoinstellingar" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -419,72 +447,25 @@ msgstr "Endra kontoinstellingar" msgid "Media processing panel" msgstr "Verkprosesseringspanel" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "Logg ut" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Legg til verk" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Lag ny samling" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by MediaGoblin, a GNU project." -msgstr "Drive av MediaGoblin, eit GNU-prosjekt." - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Lisensiert med AGPL. Kjeldekode er tilgjengeleg." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "Bilete av stressa goblin" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Utforsk" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Heihei, velkomen til denne MediaGoblin-sida." - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Denne sida køyrer MediaGoblin, eit superbra program for å visa fram dine kreative verk." - -#: 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 "Vil du leggja til eigne verk og innpel, so må du logga inn." - -#: mediagoblin/templates/mediagoblin/root.html:38 -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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Opprett ein konto på denne sida eller set opp MediaGoblin på eigen tenar" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Nyaste verk" @@ -590,6 +571,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "Drive av MediaGoblin, eit GNU-prosjekt." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Lisensiert med AGPL. Kjeldekode er tilgjengeleg." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Utforsk" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Heihei, velkomen til denne MediaGoblin-sida." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Denne sida køyrer MediaGoblin, eit superbra program for å visa fram dine kreative verk." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +msgid "Don't have one yet? It's easy!" +msgstr "Har du ikkje ein enno? Det er enkelt!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Legg ved vedlegg" @@ -625,12 +653,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +679,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,7 +696,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "Slett kontoen min" @@ -683,6 +725,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -707,6 +750,7 @@ msgid "" msgstr "Du kan skaffa ein moderne netlesar som kan spela av dette lydklippet hjå http://opera.com/download." #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Opphavleg fil" @@ -715,6 +759,7 @@ msgstr "Opphavleg fil" msgid "WebM file (Vorbis codec)" msgstr "WebM-fil (Vorbis-kodek)" +#: 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,6 +770,10 @@ msgstr "WebM-fil (Vorbis-kodek)" msgid "Image for %(media_title)s" msgstr "Bilete for %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "Slå av/på rotering" @@ -823,7 +872,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 +915,28 @@ msgstr "%(username)s sine verk" msgid "❖ Browsing media by %(username)s" msgstr "❖ Ser på %(username)s sine verk" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Legg att innspel" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Lagt til

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1039,7 +1092,7 @@ msgstr "eldre" 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." @@ -1069,6 +1122,30 @@ msgid "" " deleted." msgstr "Ser ikkje ut til å finnast noko her. Orsak.

\n

Dersom du er sikker på at adressa finst, so er ho truleg flytta eller sletta." +#: 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 "Innspel" @@ -1100,73 +1177,77 @@ msgstr "-- Vel --" msgid "Include a note" msgstr "Legg ved eit notat" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "kom med innspel på innlegget ditt" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Vops, innspelet ditt var tomt." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Innspelet ditt er lagt til." -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Du sletta verket." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Samlinga «%s» sletta" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index ea905b6178aa7f9229202950d28f79227a796f5a..5a234c8276f4ccbcaa752cc934bb5ae29bb23ab4 100644 GIT binary patch delta 7602 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 Mz~w_dzHRw`0UCTF#{d8T diff --git a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po index 9edf8e2b..5a36889a 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ć , 2012. +# Daniel Koć , 2012 +# Sergiusz Pawlowicz , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +20,39 @@ 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/auth/forms.py:30 -msgid "This field requires an email address." -msgstr "" - -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Użytkownik" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Hasło" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Adres e-mail" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Użytkownik lub adres e-mail" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Nieprawidłowa nazwa konta albo niewłaściwy adres poczty elektronicznej." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Niniejsze pole nie jest przeznaczone na adres poczty elektronicznej." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Niniejsze pole wymaga podania adresu poczty elektronicznej." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Niestety rejestracja w tym serwisie jest wyłączona." @@ -59,54 +65,54 @@ msgstr "Niestety użytkownik o takiej nazwie już istnieje." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "Wyślij ponownie e-mail weryfikujący." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 msgid "" "If that email address (case sensitive!) is registered an email has been sent" " with instructions on how to change your password." -msgstr "" +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/auth/views.py:261 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." -msgstr "" +msgstr "Nie potrafię znaleźć nikogo o tej nazwie użytkownika." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." -msgstr "Teraz możesz się zalogować używając nowe hasło." +msgstr "Teraz możesz się zalogować używając nowego hasła." -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -117,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -133,11 +139,11 @@ msgstr "Znaczniki" msgid "Separate tags by commas." msgstr "Rozdzielaj znaczniki przecinkami." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Slug" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Slug nie może być pusty" @@ -165,45 +171,45 @@ 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:67 -msgid "New password" -msgstr "Nowe hasło" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" -msgstr "" +msgstr "Ulubiona licencja" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 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 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Opis tej kolekcji" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "Stare hasło" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nowe hasło" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Adres z tym slugiem dla tego użytkownika już istnieje." @@ -214,11 +220,11 @@ msgstr "Edytujesz media innego użytkownika. Zachowaj ostrożność." #: mediagoblin/edit/views.py:155 #, python-format msgid "You added the attachment %s!" -msgstr "" +msgstr "Dodałeś załącznik %s!" #: mediagoblin/edit/views.py:182 msgid "You can only edit your own profile." -msgstr "" +msgstr "Masz możliwość edycji tylko własnego profilu." #: mediagoblin/edit/views.py:188 msgid "You are editing a user's profile. Proceed with caution." @@ -228,57 +234,80 @@ msgstr "Edytujesz profil innego użytkownika. Zachowaj ostrożność." 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:240 msgid "Account settings saved" msgstr "Zapisano ustawienia konta" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "Kolekcja \"%s\" już istnieje!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 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:329 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:348 +msgid "Wrong password" +msgstr "Nieprawidłowe hasło" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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 "" + +#: 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.
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.
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:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Konwersja wideo nie powiodła się" @@ -315,7 +344,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,17 +374,17 @@ msgstr "Przekierowanie URI dla aplikacji, to pole\n jest 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:56 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/templates/mediagoblin/submit/collection.html:30 @@ -364,7 +393,7 @@ msgstr "" msgid "Add" msgstr "Dodaj" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Niewłaściwy plik dla tego rodzaju mediów." @@ -372,45 +401,45 @@ msgstr "Niewłaściwy plik dla tego rodzaju mediów." msgid "File" msgstr "Plik" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Musisz podać plik." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Hura! Wysłano!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "Kolekcja \"%s\" została dodana!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Zweryfikuj swój adres e-mail!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" -msgstr "" +msgstr "wyloguj się" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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ę" -#: mediagoblin/templates/mediagoblin/base.html:79 +#: mediagoblin/templates/mediagoblin/base.html:82 #, python-format msgid "%(user_name)s's account" -msgstr "" +msgstr "konto %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Zmień ustawienia konta" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -418,72 +447,25 @@ msgstr "Zmień ustawienia konta" msgid "Media processing panel" msgstr "Panel przetwarzania mediów" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" -msgstr "" - #: mediagoblin/templates/mediagoblin/base.html:96 +msgid "Log out" +msgstr "Wyloguj się" + +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Dodaj media" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Opublikowane na licencji AGPL. Dostępny jest kod źródłowy." +msgstr "Utwórz nową kolekcję" #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" -msgstr "" +msgstr "Grafika zestresowanego goblina" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Odkrywaj" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Cześć, witaj na stronie MediaGoblin!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Ten serwis działa w oparciu o MediaGoblin, świetne oprogramowanie do publikowania mediów." - -#: 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 "Aby dodawać swoje pliki, komentować i wykonywać inne czynności, możesz się zalogować na swoje konto MediaGoblin." - -#: mediagoblin/templates/mediagoblin/root.html:38 -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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Utwórz konto w tym serwisie\n lub\n załóż własny serwis MediaGoblin" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Najnowsze media" @@ -589,6 +571,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "Napędzane przez oprogramowanie MediaGoblin, będące częścią projektu GNU." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Opublikowane na licencji AGPL. Dostępny jest kod źródłowy." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Odkrywaj" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Cześć, witaj na stronie MediaGoblin!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Ten serwis działa w oparciu o MediaGoblin, świetne oprogramowanie do publikowania mediów." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +msgid "Don't have one yet? It's easy!" +msgstr "Jeszcze go nie masz? To proste!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Dodaj załącznik" @@ -624,23 +653,33 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 "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,10 +696,14 @@ 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 -msgid "Delete my account" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 +msgid "Delete my account" +msgstr "Usuń moje konto" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -682,6 +725,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -706,6 +750,7 @@ msgid "" msgstr "Proszę pobrać przeglądarkę, która obsługuje \n\tdźwięk w HTML5, pod adresem \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Oryginalny plik" @@ -714,6 +759,7 @@ msgstr "Oryginalny plik" msgid "WebM file (Vorbis codec)" msgstr "plik WebM (kodek Vorbis)" +#: 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,59 +770,63 @@ msgstr "plik WebM (kodek Vorbis)" msgid "Image for %(media_title)s" msgstr "Grafika dla %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" -msgstr "" +msgstr "Obróć" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 msgid "Perspective" -msgstr "" +msgstr "Perspektywa" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:116 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:117 msgid "Front" -msgstr "" +msgstr "Początek" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:120 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:121 msgid "Top" -msgstr "" +msgstr "Góra" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:124 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:125 msgid "Side" -msgstr "" +msgstr "Krawędź" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:130 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:131 msgid "WebGL" -msgstr "" +msgstr "WebGL" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:138 msgid "Download model" -msgstr "" +msgstr "Pobierz model" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:146 msgid "File Format" -msgstr "" +msgstr "Format pliku" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:148 msgid "Object Height" -msgstr "" +msgstr "Wysokość obiektu" #: mediagoblin/templates/mediagoblin/media_displays/video.html:44 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 msgid "" "You can get a modern web browser that \n" " can play this video at \n" " http://getfirefox.com!" -msgstr "" +msgstr "Możesz pobrać porządną przeglądarkę, która jest w stanie odtworzyć ten materiał filmowy, ze strony ⏎ http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/video.html:69 msgid "WebM file (640p; VP8/Vorbis)" @@ -822,19 +872,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 "%(username)s's collections" -msgstr "" +msgstr "kolekcje użytkownika %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -853,7 +903,7 @@ msgstr "Media użytkownika %(username)s" msgid "" "%(username)s's media with tag %(tag)s" -msgstr "" +msgstr "pliki użytkownika %(username)s z tagiem %(tag)s" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -865,30 +915,34 @@ msgstr "media użytkownika %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "❖ Przeglądanie mediów użytkownika %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Dodaj komentarz" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Dodane

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +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 "Dodaj “%(media_title)s” do kolekcji" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" @@ -967,7 +1021,7 @@ msgstr "Ten użytkownik nie wypełnił (jeszcze) opisu swojego profilu." #: mediagoblin/templates/mediagoblin/user_pages/user.html:124 msgid "Browse collections" -msgstr "" +msgstr "Przeglądaj kolekcje" #: mediagoblin/templates/mediagoblin/user_pages/user.html:137 #, python-format @@ -988,15 +1042,15 @@ msgstr "Tu nie ma jeszcze żadnych mediów..." #: 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 @@ -1038,7 +1092,7 @@ msgstr "starsze" 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." @@ -1048,29 +1102,53 @@ msgstr "Ups!" #: mediagoblin/tools/response.py:36 msgid "An error occured" -msgstr "" +msgstr "Wystąpił błąd" #: mediagoblin/tools/response.py:51 msgid "Operation not allowed" -msgstr "" +msgstr "Operacja niedozwolona" #: mediagoblin/tools/response.py:52 msgid "" "Sorry Dave, I can't let you do that!

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ć!

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 msgid "" "There doesn't seem to be a page at this address. Sorry!

If you're sure" " the address is correct, maybe the page you're looking for has been moved or" " deleted." +msgstr "Wygląda na to, że nic tutaj nie ma!

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 "" + +#: 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 "Komentarz" #: mediagoblin/user_pages/forms.py:25 msgid "" @@ -1089,7 +1167,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 +1177,77 @@ msgstr "-- wybierz --" msgid "Include a note" msgstr "Dodaj notatkę" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "komentarze do twojego wpisu" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 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:180 msgid "Your comment has been posted!" msgstr "Twój komentarz został opublikowany!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Media zostały usunięte." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Usunięto kolekcję \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index af50e0273612cd852a6abdbee04aa0ec8bbeb614..5e83a7f261bc6b193b598c1e71b38c414865b909 100644 GIT binary patch delta 5542 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 HoiqBsK, 2013. -# , 2011. -# ufa , 2011. -# Vinicius SM , 2013. +# osc , 2013 +# Rafael Ferreira , 2013 +# osc , 2011 +# ufa , 2011 +# 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/mediagoblin/language/pt_BR/)\n" "MIME-Version: 1.0\n" @@ -22,34 +23,39 @@ msgstr "" "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "Nome de usuário ou email inválido." - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "Este campo não aceita endereços de email." - -#: mediagoblin/auth/forms.py:30 -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 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Nome de Usuário" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Senha" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Endereço de email" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Nome de usuário ou email" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Nome de usuário ou email inválido." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Este campo não aceita endereços de email." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Este campo requer um endereço de email." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Desculpa, o registro está desativado neste momento." @@ -62,54 +68,54 @@ msgstr "Desculpe, um usuário com este nome já existe." 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:182 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:188 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:206 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:214 msgid "You've already verified your email address!" msgstr "Você já verificou seu email!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "O email de verificação foi enviado novamente." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 msgid "" "If that email address (case sensitive!) is registered an email has been sent" " with instructions on how to change your password." -msgstr "" +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/auth/views.py:261 +#: mediagoblin/auth/views.py:269 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 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -120,7 +126,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -136,11 +142,11 @@ msgstr "Etiquetas" 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:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Arquivo" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "O arquivo não pode estar vazio" @@ -168,45 +174,45 @@ 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:67 -msgid "New password" -msgstr "Nova senha" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "Licença preferida" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 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 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "Senha antiga" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nova senha" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Uma entrada com esse arquivo já existe para esse usuário" @@ -231,44 +237,63 @@ msgstr "Você está editando um perfil de usuário. Tenha cuidado." 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:240 msgid "Account settings saved" msgstr "As mudanças na conta foram salvas" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 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:329 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:348 +msgid "Wrong password" +msgstr "Senha errada" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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 "" + +#: 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,12 +301,16 @@ msgid "" "domain." msgstr "Cookie CSFR não está presente. Isso é provavelmente o resultado de um bloqueador de cookies ou algo do tipo.
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:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Conversão do vídeo falhou" @@ -348,7 +377,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:56 msgid "The client {0} has been registered!" msgstr "O cliente {0} foi registrado!" @@ -367,7 +396,7 @@ msgstr "Seus clientes OAuth" msgid "Add" msgstr "Adicionar" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Arquivo inválido para esse tipo de mídia" @@ -375,45 +404,45 @@ msgstr "Arquivo inválido para esse tipo de mídia" msgid "File" msgstr "Arquivo" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Você deve fornecer um arquivo." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Eba! Enviado!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "Coleção \"%s\" adicionada!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Verifique seu email!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "sair" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "Conta de %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 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/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -421,72 +450,25 @@ msgstr "Mudar configurações da conta" msgid "Media processing panel" msgstr "Painel de processamento de mídia" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" -msgstr "" - #: mediagoblin/templates/mediagoblin/base.html:96 +msgid "Log out" +msgstr "Sair" + +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Adicionar mídia" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Lançado sob a AGPL. Código fonte disponível." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" -msgstr "" +msgstr "Imagem do goblin se estressando" -#: 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Este site roda o MediaGoblin, 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Criar uma conta neste site\nou\nConfigurar MediaGoblin em seu próprio servidor" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Mídia mais recente" @@ -592,6 +574,53 @@ 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 MediaGoblin, a GNU project." +msgstr "Fornecido pelo MediaGoblin, um projeto GNU." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Lançado sob a AGPL. Código fonte disponível." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Explorar" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +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 MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Este site roda o MediaGoblin, um programa excelente para hospedar, gerenciar e compartilhar mídia." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr " Ainda não tem uma conta? É facil!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -604,13 +633,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Adicionar anexo" @@ -627,12 +656,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +682,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,7 +699,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "Deletar minha conta" @@ -685,6 +728,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -709,6 +753,7 @@ msgid "" msgstr "Você pode obter um navegador moderno\n »capaz de reproduzir o áudio em \n » http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Arquivo original" @@ -717,6 +762,7 @@ msgstr "Arquivo original" msgid "WebM file (Vorbis codec)" msgstr "Arquivo WebM (codec Vorbis)" +#: 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,6 +773,10 @@ msgstr "Arquivo WebM (codec Vorbis)" msgid "Image for %(media_title)s" msgstr "Imagem para %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "Alternar Rotação" @@ -825,7 +875,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 +906,7 @@ msgstr "Mídia de %(username)s's" msgid "" "%(username)s's media with tag %(tag)s" -msgstr "" +msgstr "Mídias de %(username)s com a etiqueta %(tag)s" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -868,24 +918,28 @@ msgstr "Mídia de %(username)s " msgid "❖ Browsing media by %(username)s" msgstr "❖ Vendo mídia de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Adicionar um comentário" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Adicionado em

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -987,7 +1041,7 @@ msgstr "Aqui é onde sua mídia vai aparecer, mas parece que você não adiciono #: 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/utils/collection_gallery.html:49 msgid "(remove)" @@ -999,7 +1053,7 @@ msgstr "" #: 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 @@ -1041,7 +1095,7 @@ msgstr "mais antiga" 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." @@ -1071,6 +1125,30 @@ msgid "" " deleted." msgstr "Parece que não há uma página com este endereço. Desculpe!

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 "" + +#: 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 "Comentário" @@ -1096,79 +1174,83 @@ 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 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "comentou na sua publicação" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Ops, seu comentário estava vazio." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Seu comentário foi postado!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Você deletou a mídia." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, 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:422 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:430 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 index 62cbf0287c6f3d19078ce2e54d0411209816e7c8..309855f53d314f691dc1ab8dd06bf063678cc403 100644 GIT binary patch delta 5199 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 hE?3?OA&pGeqoaa2x zIlEr@Fr@vx5MNjC@V$ngulP5Re;Xpy``^#CSYwjueu0DV5$0o3Ph-YnH4eZZU|&3h z{qQVC;-?sb*RTh6;SIclBaHExkK>FP#f8vb#tg^NxBypRCjJ_?Fv1-yrtj%vPw-O= zqu+rHVLreZ{2Ud?EhJX+7`tOM7xi2`a>-<1Ec2TZ8rfW!9K7MdZuGZc5$?cA*nv|p zCf*KsK5D=pq9)jn(fB4Ru#?yu&tN-t;#0Vs^rYe{OkjSqi$)e6My2Q?MqwB7Yi{%B zNmUYzNueK!EtrW4{1w!|ou~;vMdmU$Q2{;<-j7K%h9sK4sOK`!7fz#?h9WORO)v%d zH4XexZ8rw5??ct}EGo6w|D2=HM{&;EQ+wKf{zHCc_7qgEd4q65CLl`Q3r! ze>9D&Txi8UZ1r`x8=2GeARXHM8K_NDiCX!5Ov8FqEw>|cnq#O1e27Z%MO4PVM3v|- z!Ta}v_aFOcXyBfNqgtn-A}isKYPSGYvz4ffyogHmM%2VRQ4<|Uy?-7R$Tg%2<{>KO zahCmF3Tm_Fpfc$jMMEnbgGzA?Dq=V4#TSD8&8U>`MAhyk+>9Nl_ofcECv@OA`You; z{sOg-2dKa!hV? z_&UCV3UtyC`?x-j!{{GEW#|$X==}ec#sV%3PB*3&H=tH}9mDY}WGwSFPQ~~PW2(@B z6Yvmf*WX1KMrYc)zXcWeZk&T};dJ~rDv;?!caZtbdK!6{%we{$8a3c5vp6kB}+uEcKmGA_Z_P$dmx_Au;)PtJcljYuvGK&3nlwW&s- zRxk-Ibf6~Mh#L4fD$vuY=PqLe-bKCt0AsOxuD!<+QO_44v6?x#e2K>jJ4 zi6&nqI0ChjRmd}DGirj<*c-n@otB5Fl*Sj@1A8%){vOo8Kf&&J43&}7sEqw8==;I@ zojw}h;l}UqA0ZqIKAsd%Oc5IrMS)@rTeIB*aHdIP? z2K#$a6Ya;n_zr5^>M~;(!py~i_#;%Qk710?|7{u?@FAvP2zk~@EL28va5K(B_MiCz zby|9q+bNDmtuzzkupBkpDLjF(_%SNdF4RPiPy>Wl z*aP%KJ(q%dE*BGU3MSz)w6GNw(0(Kt=I6+XGv*1ip+zm?RwOUyHJ@p zh^pyPoP%dE8{;^u8?Xc~<0*UrcU0P+6Hisy$GHeCuD2k`GcRE${=SO*t5%06*r_j@ zXs>87YIC)qQn(AXH(o`mWIn?|*pH2&3>BgF##rozb1(*LFaqmQ8FHgayaiRVHztvP zj(uQ zbowc%l2`g@MACQ;wbB)+h}WYg-h`T97jDNh!G0A5)Ics=hI^2#n}?`Olvdj%n~Cl8 zm!ih~Cn|HH)9i75sWcSvR8-1qF%#FJ0y>CF)d|!97cd4d<8yceU&ry&?bC7_six^W z!#-vUF`xdAu^fMcTQPDbi`4nwO+&jlc9uPG4i2VYjErp-B8xU}qE>hx6>#xvzKC!Z zD&R|~-TxRHF_E3>!Zyst`=~%u=Gy<)?7(cD|3@?|ZlphB?}Z6ChW=vz`OSP9ihN_xmr*Hu7l-2= z)WAtKcI^hEp07ZaWHI(YCu-nkOvN@-sScwu`VKC_E2zwlT0s68+iaqt6<9yGY$X$Rd=>H89v1W<=W!8)d^xJV5zKxovYYF*R zWU1^V4OoeKz=QfAI)H=lB(B5DsAD%{sr_~9#dP{>u{-WVW#mxMpP{aw!e~5)91wE> zO=`L))$)hN9re$NOYmQdI}%}8?&c`V3T*A=3Q1p4SXNP2=d82buF~OjxS^lYrn2;` zI)~Sp?I|7J6u94eduX67zBttXuY^ASTM51W0}{*qI};xTcK45u^#69SGfue{NLbz~xTnXsC6&OryKra`Te{03Kz~3t}LIP>yk97BcUH!el`e_$K{j+9%Kk)6$b0L8%v)_vh99=jt pGPKd*zgwG`ro>uGv6<}rpuM5lX;`r3ayLA2jk9(|gWp$I^B+qLU`hZ0 diff --git a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po index da585d5c..4a33f751 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: -# , 2011. -# George Pop , 2011-2013. +# George Pop , 2011 +# George Pop , 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 \n" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" +"Last-Translator: cwebber \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,34 +20,39 @@ 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 -msgid "Invalid User name or email address." -msgstr "Nume de utilizator sau adresă de e-mail nevalidă." - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "Această rubrică nu este pentru adrese de e-mail." - -#: mediagoblin/auth/forms.py:30 -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 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Nume de utilizator" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Parolă" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Adresa de e-mail" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Numele de utilizator sau adresa de e-mail" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Nume de utilizator sau adresă de e-mail nevalidă." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Această rubrică nu este pentru adrese de e-mail." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Această rubrică trebuie completată cu o adresă 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." @@ -60,54 +65,54 @@ msgstr "Ne pare rău, există deja un utilizator cu același nume." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "E-mail-ul de verificare a fost retrimis." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "Nu există nimeni cu acest nume de utilizator." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -118,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -134,11 +139,11 @@ msgstr "Cuvinte-cheie" 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:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Identificator" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Identificatorul nu poate să lipsească" @@ -166,45 +171,45 @@ 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:67 -msgid "New password" -msgstr "Noua parolă" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "Licența preferată" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 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 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "Vechea parolă" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Noua parolă" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Există deja un entry cu același identificator pentru acest utilizator." @@ -229,44 +234,63 @@ msgstr "Editezi profilul unui utilizator. Se recomandă prudență." 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:240 msgid "Account settings saved" msgstr "Setările pentru acest cont au fost salvate" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 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:329 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:348 +msgid "Wrong password" +msgstr "Parolă incorectă" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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 "" + +#: 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,12 +298,16 @@ msgid "" "domain." msgstr "Lipsește cookie-ul CSRF. Probabil că blocați cookie-urile.
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:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Transcodarea video a eșuat" @@ -346,7 +374,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:56 msgid "The client {0} has been registered!" msgstr "Clientul {0} a fost înregistrat!" @@ -365,7 +393,7 @@ msgstr "Clienții tăi OAuth" msgid "Add" msgstr "Adaugă" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Formatul fișierului nu corespunde cu tipul de media selectat." @@ -373,45 +401,45 @@ msgstr "Formatul fișierului nu corespunde cu tipul de media selectat." msgid "File" msgstr "Fișier" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Trebuie să selectezi un fișier." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Ura! Trimis!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "Colecția \"%s\" a fost creată!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Verifică adresa de e-mail!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "Ieșire" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "Contul lui %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Modifică setările contului" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -419,72 +447,25 @@ msgstr "Modifică setările contului" msgid "Media processing panel" msgstr "Panou de procesare media" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "Ieșire" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Trimite fișier" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Creează colecție nouă" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by MediaGoblin, a GNU project." -msgstr "Construit cu MediaGoblin, un proiect GNU." - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Publicat sub licența AGPL. Codul sursă este disponibil." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "Imagine cu un goblin stresat" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Explorează" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Salut, bine ai venit pe acest site MediaGoblin!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Acest site folosește MediaGoblin, un software excepțional pentru găzduirea fișierelor media." - -#: 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 "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 -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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Creează un cont pe acest site\n sau\n Instalează MediaGoblin pe serverul tău" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Cele mai recente fișiere" @@ -590,6 +571,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "Construit cu MediaGoblin, un proiect GNU." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Publicat sub licența AGPL. Codul sursă este disponibil." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Explorează" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Salut, bine ai venit pe acest site MediaGoblin!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Acest site folosește MediaGoblin, un software excepțional pentru găzduirea fișierelor media." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +msgid "Don't have one yet? It's easy!" +msgstr "Încă nu ai unul? E simplu!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Atașează" @@ -625,12 +653,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +679,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,7 +696,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "Șterge contul meu" @@ -683,6 +725,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -707,6 +750,7 @@ msgid "" msgstr "Poți lua un browser modern \n\tcapabil să redea această înregistrare de la \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Fișierul original" @@ -715,6 +759,7 @@ msgstr "Fișierul original" msgid "WebM file (Vorbis codec)" msgstr "Fișier WebM (codec Vorbis)" +#: 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,6 +770,10 @@ msgstr "Fișier WebM (codec Vorbis)" msgid "Image for %(media_title)s" msgstr "Imagine pentru %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "Rotire" @@ -823,7 +872,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 +915,28 @@ msgstr "Fișierele media ale lui %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "

❖ Fișierele media ale lui %(username)s

" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Adaugă un comentariu" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Adăugat la

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1039,7 +1092,7 @@ msgstr "mai vechi" 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." @@ -1069,6 +1122,30 @@ msgid "" " deleted." msgstr "Nu există nicio pagină la această adresă.

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 "" + +#: 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 "Comentariu" @@ -1100,73 +1177,77 @@ msgstr "-- Selectează --" msgid "Include a note" msgstr "Adaugă o notiță" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "a făcut un comentariu la postarea ta" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Hopa, ai uitat să scrii comentariul." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Comentariul tău a fost trimis!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Ai șters acest fișier" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, 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:422 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:430 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 index 759f5337473d6f258f60410f91e5dae2562eacab..89836e48ad2bbea9867b98c25cbef0ae6a5e73e8 100644 GIT binary patch delta 5307 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, 2013. -# , 2011-2012. +# aleksejrs , 2013 +# aleksejrs , 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 15:35+0000\n" -"Last-Translator: aleksejrs \n" -"Language-Team: LANGUAGE \n" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" +"Last-Translator: cwebber \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,34 +20,39 @@ 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." -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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Логин" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Пароль" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Адрес электронной почты" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Имя пользователя или адрес электронной почты" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Это поле не для адреса электронной почты." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Это поле — для адреса электронной почты." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Извините, на этом сайте регистрация запрещена." @@ -60,54 +65,54 @@ msgstr "Извините, пользователь с этим именем уж msgid "Sorry, a user with that email address already exists." msgstr "Сожалеем, но на этот адрес электронной почты уже зарегистрирована другая учётная запись." -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "Неверный ключ проверки или идентификатор пользователя" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "Вы уже потвердили свой адрес электронной почты!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "Переслать сообщение с подтверждением аккаунта." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "Не найдено никого с таким именем пользователя." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "Вам отправлено электронное письмо с инструкциями по смене пароля." -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "Теперь вы можете войти, используя ваш новый пароль." -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -118,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -134,11 +139,11 @@ msgstr "Метки" msgid "Separate tags by commas." msgstr "(через запятую)" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Отличительная часть адреса" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Отличительная часть адреса необходима" @@ -166,45 +171,45 @@ 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:67 -msgid "New password" -msgstr "Новый пароль" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "Предпочитаемая лицензия" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "Она будет лицензией по умолчанию для ваших загрузок" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "Уведомлять меня по e-mail о комментариях к моим файлам" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "Название не может быть пустым" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Описание этой коллекции" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "Старый пароль" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "Введите свой старый пароль в качестве доказательства, что это ваша учётная запись." + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "Новый пароль" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "У этого пользователя уже есть файл с такой отличительной частью адреса." @@ -229,44 +234,63 @@ msgstr "Вы редактируете профиль пользователя. msgid "Profile changes saved" msgstr "Изменения профиля сохранены" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "Неправильный пароль" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "Настройки учётной записи записаны" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "У вас уже есть коллекция с названием «%s»!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "У этого пользователя уже есть коллекция с такой отличительной частью адреса." -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "Вы редактируете коллекцию другого пользователя. Будьте осторожны." -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "Неправильный пароль" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +298,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "Увы, я не поддерживаю этот тип файлов :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Перекодировка видео не удалась" @@ -346,7 +374,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "Клиент {0} зарегистрирован!" @@ -365,7 +393,7 @@ msgstr "" msgid "Add" msgstr "Добавить" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Неправильный формат файла." @@ -373,45 +401,45 @@ msgstr "Неправильный формат файла." msgid "File" msgstr "Файл" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Вы должны загрузить файл." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Ура! Файл загружен!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "Коллекция «%s» добавлена!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Подтвердите ваш адрес электронной почты!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "завершение сеанса" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "Учётная запись %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Изменить настройки учётной записи" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -419,72 +447,25 @@ msgstr "Изменить настройки учётной записи" msgid "Media processing panel" msgstr "Панель обработки файлов" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "Завершение сеанса" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Добавить файлы" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "Работает на MediaGoblin, проекте GNU." - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Он опубликован на условиях AGPL. Доступны исходные тексты." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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’овый сайт!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Этот сайт работает на MediaGoblin, необыкновенно замечательном ПО для хостинга мультимедийных файлов." - -#: 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’овой учётной записи." - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Создайте учётную запись на этом сайте\n или\n установите MediaGoblin на собственный сервер" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Самые новые файлы" @@ -590,6 +571,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "Работает на MediaGoblin, проекте GNU." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Он опубликован на условиях AGPL. Доступны исходные тексты." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Смотреть" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Привет! Добро пожаловать на наш MediaGoblin’овый сайт!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Этот сайт работает на MediaGoblin, необыкновенно замечательном ПО для хостинга мультимедийных файлов." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "У вас её ещё нет? Не проблема!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Добавить сопутствующий файл" @@ -625,12 +653,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +679,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,7 +696,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "Удалить мою учётную запись" @@ -683,6 +725,7 @@ 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:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -707,6 +750,7 @@ msgid "" msgstr "Вы можете скачать современный браузер, \n\tспособный проиграть это аудио, с \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Исходный файл" @@ -715,6 +759,7 @@ msgstr "Исходный файл" msgid "WebM file (Vorbis codec)" msgstr "WebM‐файл (кодек — Vorbis)" +#: 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,6 +770,10 @@ msgstr "WebM‐файл (кодек — Vorbis)" msgid "Image for %(media_title)s" msgstr "Изображение «%(media_title)s»" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -823,7 +872,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 +915,28 @@ msgstr "Файлы пользователя %(username) msgid "❖ Browsing media by %(username)s" msgstr "❖ Просмотр файлов пользователя %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Добавить комментарий" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "Добавить этот комментарий" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "в" - -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Добавлено

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1039,7 +1092,7 @@ msgstr "более старые" msgid "Tagged with" msgstr "Метки" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "Не удалось прочитать файл с изображением." @@ -1069,6 +1122,30 @@ msgid "" " 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 "Комментировать" @@ -1100,73 +1177,77 @@ msgstr "-- Выберите --" msgid "Include a note" msgstr "Примечание" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "оставил комментарий к вашему файлу" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "Ой, ваш комментарий был пуст." -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "Ваш комментарий размещён!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "Пожалуйста, проверьте введённое и попробуйте ещё раз." -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "Необходимо выбрать или добавить коллекцию" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "«%s» — уже в коллекции «%s»" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "«%s» добавлено в коллекцию «%s»" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "Вы удалили файл." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "Вы исключили файл из коллекции." -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "Вы удалили коллекцию «%s»" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index bc92bb133188609abc0eebb5ef6377d60f6ef882..a262aaee810085bb96b5474038c81ebcc1555a05 100644 GIT binary patch delta 5286 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, 2013. -# Martin Zatroch , 2012. -# Morten Juhl-Johansen Zölde-Fejér , 2012. -# Olle Jonsson , 2012. -# Tanja Trudslev , 2012. -# , 2011-2012. +# martin , 2013 +# martin , 2012-2013 +# Morten Juhl-Johansen Zölde-Fejér , 2012 +# Olle Jonsson , 2012 +# ttrudslev , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +24,39 @@ msgstr "" "Language: sk\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: mediagoblin/auth/forms.py:28 -msgid "Invalid User name or email address." -msgstr "Nesprávne používateľské meno alebo e-mailová adresa." - -#: mediagoblin/auth/forms.py:29 -msgid "This field does not take email addresses." -msgstr "Toto pole neakceptuje e-mailové adresy." - -#: mediagoblin/auth/forms.py:30 -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 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Používateľské meno" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Heslo" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Email adresse" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Používateľské meno alebo e-mailová adresa" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Nesprávne používateľské meno alebo e-mailová adresa." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Toto pole neakceptuje e-mailové adresy." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Toto pole vyžaduje e-mailovú adresu." + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Prepáč, registrácia na danej inštancii nie je povolená." @@ -64,54 +69,54 @@ msgstr "Prepáč, rovnaké používateľské meno už existuje." 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:182 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:188 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:206 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:214 msgid "You've already verified your email address!" msgstr "Už máš overenú e-mailovú adresu!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "Opätovne zaslať overovací e-mail." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 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 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -122,7 +127,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -138,11 +143,11 @@ msgstr "Štítky" 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:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Unikátna časť adresy" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Unikátna časť adresy nesmie byť prázdna" @@ -170,45 +175,45 @@ 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:67 -msgid "New password" -msgstr "Nové heslo" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "Preferencia licencie" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 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 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "Popis danej kolekcie" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "Staré heslo" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Nové heslo" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Položku s rovnakou unikátnou časťou adresy už niekde máš." @@ -233,44 +238,63 @@ msgstr "Upravuješ profil iného používateľa. Pristupuj zodpovedne. " 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:240 msgid "Account settings saved" msgstr "Nastavenia účtu uložené" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 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:329 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:348 +msgid "Wrong password" +msgstr "Nesprávne heslo" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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 "" + +#: 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 " @@ -278,12 +302,16 @@ msgid "" "domain." msgstr "CSRF \"cookie\" neprítomný. Toto vidíš najskôr ako výsledok blokovania \"cookie\" súborov a pod.
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:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Konvertovanie videa zlyhalo" @@ -350,7 +378,7 @@ msgstr "Presmerovacie URI pre aplikácie, toto pole\nje požadované%(user_name)s's account" msgstr "Účet používateľa %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Zmeniť nastavenia účtu" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -423,72 +451,25 @@ msgstr "Zmeniť nastavenia účtu" msgid "Media processing panel" msgstr "Sekcia spracovania výtvorov" -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" -msgstr "" - #: mediagoblin/templates/mediagoblin/base.html:96 +msgid "Log out" +msgstr "Odhlásiť sa" + +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Pridať výtvor" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Vytvoriť novú kolekciu" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by MediaGoblin, a GNU project." -msgstr "Poháňa nás MediaGoblin, súčasť projektu GNU." - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Uvoľnené pod AGPL. Zdrojový kód plne dostupný." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" msgstr "Obrázok hysterického goblina" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Preskúmať" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Ahoj, vitaj na tejto MediaGoblin stránke!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Táto stránka používa MediaGoblin, výnimočne skvelý kus softvéru na hostovanie médií." - -#: 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 "Pre pridanie vlastných výtvorov, komentárov a viac.. sa prihlás zo svojim MediaGoblin účtom." - -#: 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/templates/mediagoblin/root.html:39 -#, python-format -msgid "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Vytvoriť účet na tejto stránke\n alebo\n Založiť MediaGoblin na vlastnom serveri" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Aktuálne výtvory" @@ -594,6 +575,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "Poháňa nás MediaGoblin, súčasť projektu GNU." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Uvoľnené pod AGPL. Zdrojový kód plne dostupný." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Preskúmať" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Ahoj, vitaj na tejto MediaGoblin stránke!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Táto stránka používa MediaGoblin, výnimočne skvelý kus softvéru na hostovanie médií." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +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:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -606,13 +634,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Pridať prílohu" @@ -629,12 +657,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +683,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,7 +700,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "Odstrániť môj účet" @@ -687,6 +729,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -711,6 +754,7 @@ msgid "" msgstr "Môžeš získať moderný prehliadač, ktorý\n\ttento zvuk hravo prehrá \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Originálny súbor" @@ -719,6 +763,7 @@ msgstr "Originálny súbor" msgid "WebM file (Vorbis codec)" msgstr "WebM súbor (Vorbis kodek)" +#: 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,6 +774,10 @@ msgstr "WebM súbor (Vorbis kodek)" msgid "Image for %(media_title)s" msgstr "Obrázok pre %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "Zapnúť rotáciu" @@ -827,7 +876,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 +919,28 @@ msgstr "Výtvory, ktoré vlastní %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "❖ Prehliadanie výtvorov od %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Pridať komentár" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Pridané

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1043,7 +1096,7 @@ msgstr "staršie" 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." @@ -1073,6 +1126,30 @@ msgid "" " deleted." msgstr "Zdá sa, že na tejto adrese sa nič nenachádza. Prepáč!

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 "" + +#: 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 "Komentár" @@ -1104,73 +1181,77 @@ msgstr "-- Vybrať --" msgid "Include a note" msgstr "Pridať poznámku" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "okmentoval tvoj príspevok" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 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:180 msgid "Your comment has been posted!" msgstr "Tvoj komentár bol pridaný!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "Výtvor bol tebou odstránený." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, 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:422 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:430 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 index dd3de81beedab0dfad2e262f60c9ba33f1fb4c71..199e761cfc73a72c8d77e73d29acedf2c69b4ce3 100644 GIT binary patch delta 5191 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 T!qny7##-l7^-Z<^W9k0}uO2)T diff --git a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po index 98d62d59..35635acf 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 , 2011. +# Jure Repinc , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +19,39 @@ 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/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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Uporabniško ime" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Geslo" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "E-poštni naslov" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "Oprostite, prijava za ta izvod ni omogočena." @@ -59,54 +64,54 @@ msgstr "Oprostite, uporabnik s tem imenom že obstaja." msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 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:206 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:214 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "Ponovno pošiljanje potrditvene e-pošte." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -117,7 +122,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -133,11 +138,11 @@ msgstr "Oznake" msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Oznaka" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Oznaka ne sme biti prazna" @@ -165,45 +170,45 @@ 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:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Vnos s to oznako za tega uporabnika že obstaja." @@ -228,44 +233,63 @@ msgstr "Urejate uporabniški profil. Nadaljujte pazljivo." msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +297,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -345,7 +373,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -364,7 +392,7 @@ msgstr "" msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Za vrsto vsebine je bila podana napačna datoteka." @@ -372,45 +400,45 @@ msgstr "Za vrsto vsebine je bila podana napačna datoteka." msgid "File" msgstr "Datoteka" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Podati morate datoteko." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Juhej! Poslano." -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -418,72 +446,25 @@ msgstr "" msgid "Media processing panel" msgstr "Podokno obdelovanja vsebine" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Dodaj vsebino" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "" @@ -589,6 +570,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +629,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -624,12 +652,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +678,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,7 +695,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -682,6 +724,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -706,6 +749,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -714,6 +758,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +769,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -822,7 +871,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 +914,27 @@ msgstr "Vsebina uporabnika %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1038,7 +1091,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1068,6 +1121,30 @@ msgid "" " 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 "" @@ -1099,73 +1176,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index 276f1273b5136a4b85fba65bc1589c78f032d2ff..0f113dcbf07623406959c7f6b2235080cbf36ba5 100644 GIT binary patch delta 6615 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 ZNB#it9_=o!`N$Xlr+@D|-gDhM{tvXsgU0{> delta 4795 zcmaLZdvH|M9l-IEha`lAJjfGBaswoRgghk)2?4`9CLsiZ2nfO^dr5AR-Hp2&YXGwy zD$r^v%BfQ`j-u3xnEEJNr=ZYkfz}6YWkfq7QrlX5A&wNaQ?T^=UWGE@4^S4^gJW<%N?^}n3Le5?Jb|NdBk7rh9?W2UbuW#n_ykIdPGTIM zMSj&s{JB<@45f1D$Koa|L!q2 zBLB42Fn_8sjIz^@Q6|2K64+NLJBlJ2DNPp2crGr+Vw{cvyb~Y6KVr@V7Q-*G7*`YB z4BUotn4h0W{%6uS&AdTg_E%hrIz;~YpSPFHt-5c zicg|s?0u9Hed@e^$$9-sh=xp@NH|jK$taQ4@keU62Bl`bC>gmECDmI|7T$%j&;gY9 zA4dt~3{nO46-vsJ4EudKD2KHeC6l2l8nVM#C@Efz60r~EjdwWx?IVsYpgb>MJcPZbsXivzoG2>BFavp$+wJW zqbyj2l92|-g?KalCj1HRMG3TVihW&g!|C+*p=9V3R>=MTjK&%U^757H#4RX0eGjAY zJTjO19Gfw%K&gf3!bP|b<{ zG#arCj7LfNWRycyg|dT2G|+{z&{mX*51<5k5aqcyF$OQ7y#Grai=#{IGnR?+d^HlQ zYA+%GH_;ekpb<~ue9R^tHR!?y9L8CA8n<9NQEWqvY)WO7+a+3vi|Jdq8-Io-E~v22 z){`h1eHG=lT&f`dlueBxUv*fCvJ(&TjM|Q}z(GvG_fc-kS12h>yWXBSh>`Svh%)hy za5O%Rl97Wb8GF(3H_q!PLNsRc!drMUf@{IYliY%HRrW{bsA{{GrP#o@3+43g#dJL4 zcnU|+{{)#vT|^1^5?;m_(#aAkYNmY~YEU*9^3agezXv5X|HM7aFs0T$-N#6aoc=N7 zUlu4sxqj6s3$&orbUmix7L3RHoc_Z&j(*tb{}yGPGngm$e^k9a@l+&ORfcW25#>Jr z0vj-qG$msjj=>I0K(Eu^f)dboaTp&&NqyBErRL&n%*GH(CLY3gx&J3=#4&IdGw~yo zH%8uI?>r7i=$E2Iej4TV=mt9z@hI<`gtF6FD4AM{67WitjCG@o5238L4Rb;??xi6U zJcASPW#r(h_fdA5M))#u9?Bc5P$q6bDa~@s!P_w(@5f4f0VP8hkgBRHI1#Jn*_mCA zA(`+=8gl=i!?E~Flt6xm@(K8nGkyW3G+$#8wsKc@;~*wPkj@24`RR{eXkXu*$fN2w zPQlnk_BAfSA^O%L@_!eN4;hfiJd5ob-HnO#pTG<}h_chyQBLh8lnD#?(1^xnOu;s% z-|5(mF^qdq<{LoCS5a!8w8T!;bd-o2P$uZW zc?jFd~gjazXt-&k^;9>@LoC#=Npv8_>f7zgnvCgALwokQx_hRKZIgcDd_ zb3UuXE;ClzS@lNjf)f!quf_Or$HQU#iNSxY1+{tJCLI zeZDTkHxN`_^IN80`TE?ZuCG2^aeYbo45MOZUHOcX^6K*PxVEJw%gx)ZfaUX+EFh3N zqq1Bc;PPpkPf;@b8W*6yfn_FFwZuVr|9j*b|8tl{!oUL$B4y@N);3Yzt0 zuK(OcHxP97$sF!()A0Mvt^wwuyTo)`uEoBNKFeET&l%`GI^ypb zGy|5=GvMmceRZ`uG9_DYu8z}dQxf%=y2}6df1OfQNM75!g99$V;W;|;f70xkbzh{e zNJ~xSX<6ALD;vC#O?h>DT5-5@&ejP1YWh?9P(!z_nOil^*Vkuu1|_#%HQ(;&eRH#8 z=KDMz(;L)R=bqHLSw;HlyynbBfo`kER13^Llf-xi4OeHUZ@?Q2`{qZE(huZ>bbQlZ zJ(8QF-)fqw&*x6j<;_*it)#No@|Z!xG!_kb-B!>DlH>M)-hdehbbCzIVlr!s)oFSI zrqS;=H=2Ia+i9wmrq`_+2fdbRv1_iMZ7xl2BX|7+Ud!W5v_yZ_d`@r4%Svi-`I(ud zF74px)JsY7nlvL}TYlae5_`16KOk=q($hp#` zw`A*oHKm6GwdeSsi5zII%c)$8+; Z!G8aMzsC%8E4S6>we$pcwzk|W{te5%0tNs8 diff --git a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po index 5c965623..aabf18db 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 , 2012. -# FIRST AUTHOR , 2012. +# Besnik , 2012-2013 +# FIRST AUTHOR , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" "Language-Team: Albanian (http://www.transifex.com/projects/p/mediagoblin/language/sq/)\n" "MIME-Version: 1.0\n" @@ -20,34 +20,39 @@ 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/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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Emër përdoruesi" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Fjalëkalim" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Adresë email" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "Emër përdoruesi ose email" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "Emër përdoruesi ose adresë email e pavlefshme." + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "Kjo fushë nuk është për adresa email." + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "Kjo fushë lyp një adresë 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." @@ -60,54 +65,54 @@ msgstr "Na ndjeni, ka tashmë një përdorues me këtë emër." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "Ridërgoni email-in tuaj të verifikimit." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 msgid "" "If that email address (case sensitive!) is registered an email has been sent" " with instructions on how to change your password." -msgstr "" +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/auth/views.py:261 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." -msgstr "" +msgstr "S'u gjet dot dikush me atë emër përdoruesi." -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 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 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 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/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -118,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -134,11 +139,11 @@ msgstr "Etiketa" msgid "Separate tags by commas." msgstr "Ndajini etiketat me presje." -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Identifikues" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Identifikuesi s'mund të jetë i zbrazët" @@ -166,45 +171,45 @@ 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:67 -msgid "New password" -msgstr "Fjalëkalimi i ri" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" -msgstr "" +msgstr "Parapëlqime licence" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 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 +#: mediagoblin/edit/forms.py:71 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:83 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:85 mediagoblin/submit/forms.py:50 #: 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:92 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:99 +msgid "Old password" +msgstr "Fjalëkalimi i vjetër" + +#: mediagoblin/edit/forms.py:101 +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:104 +msgid "New password" +msgstr "Fjalëkalimi i ri" + +#: mediagoblin/edit/views.py:67 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." @@ -219,7 +224,7 @@ msgstr "Shtuat bashkangjitjen %s!" #: mediagoblin/edit/views.py:182 msgid "You can only edit your own profile." -msgstr "" +msgstr "Mund të përpunoni vetëm profilin tuaj." #: mediagoblin/edit/views.py:188 msgid "You are editing a user's profile. Proceed with caution." @@ -229,57 +234,80 @@ msgstr "Po përpunoni profilin e një përdoruesi. Hapni sytë." 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:240 msgid "Account settings saved" msgstr "Rregullimet e llogarisë u ruajtën" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, 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:314 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:329 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:348 +msgid "Wrong password" +msgstr "Fjalëkalim i gabuar" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +msgstr "" + +#: 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 "" + +#: 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.
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ë.
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:111 +#: mediagoblin/media_types/__init__.py:155 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:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "Ndërkodimi i videos dështoi" @@ -346,17 +374,17 @@ msgstr "URI ridrejtimi për zbatimin, kjo fushë\n është 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:56 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/templates/mediagoblin/submit/collection.html:30 @@ -365,7 +393,7 @@ msgstr "" msgid "Add" msgstr "Shtoni" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Kartelë e gabuar e dhënë për llojin e medias." @@ -373,118 +401,71 @@ msgstr "Kartelë e gabuar e dhënë për llojin e medias." msgid "File" msgstr "Kartelë" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Duhet të jepni një kartelë." -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Yhaaaaaa! U parashtrua!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "U shtua koleksioni \"%s\"!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Verifikoni email-in tuaj!" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "dilni" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "Llogaria e %(user_name)s" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "Ndryshoni rregullime llogarie" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: 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 "Paneli i Përpunimit të Medias" - -#: mediagoblin/templates/mediagoblin/base.html:93 -msgid "Log out" -msgstr "" +msgstr "Paneli i përpunimit të medias" #: mediagoblin/templates/mediagoblin/base.html:96 +msgid "Log out" +msgstr "Dilni" + +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Shtoni media" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41 msgid "Create new collection" msgstr "Krijoni koleksion të ri" -#: mediagoblin/templates/mediagoblin/base.html:122 -#, python-format -msgid "" -"Powered by MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "Hedhur në qarkullim sipas AGPL-së. Kodi burim është i passhëm." - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" -msgstr "" +msgstr "Figurë e gungaçi duke bërë shtriqje" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "Explore" -msgstr "Eksploroni" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "Tungjatjeta juaj, mirë se vini te ky site MediaGoblin!" - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "Ky site përdor MediaGoblin, një program jashtëzakonisht i shkëlqyer për strehim mediash." - -#: 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 "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 -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 -msgid "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "Krijoni një llogarin te ky site\n ose\n Instaloni dhe rregulloni MediaGoblin-in te shërbyesi juaj" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Mediat më të reja" @@ -515,7 +496,7 @@ 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" +msgstr "10 ngarkimet e fundit të suksesshme" #: mediagoblin/templates/mediagoblin/admin/panel.html:112 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107 @@ -590,6 +571,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "Bazuar në MediaGoblin, një projekt GNU." + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "Hedhur në qarkullim sipas AGPL-së. Kodi burim është i passhëm." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Eksploroni" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Tungjatjeta juaj, mirë se vini te ky site MediaGoblin!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "Ky site përdor MediaGoblin, një program jashtëzakonisht i shkëlqyer për strehim mediash." + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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/bits/frontpage_welcome.html:27 +msgid "Don't have one yet? It's easy!" +msgstr "Nuk keni ende një të tillë? Është e lehtë!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "Shtoni bashkangjitje" @@ -625,23 +653,33 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 "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,10 +696,14 @@ 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 -msgid "Delete my account" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." msgstr "" +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 +msgid "Delete my account" +msgstr "Fshije llogarinë time" + #: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29 #, python-format msgid "Editing %(collection_title)s" @@ -683,6 +725,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -707,6 +750,7 @@ msgid "" msgstr "Një shfletues web modern që mund të luajë \n\taudion mund ta merrni te \n\t http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "Kartela origjinale" @@ -715,6 +759,7 @@ msgstr "Kartela origjinale" msgid "WebM file (Vorbis codec)" msgstr "Kartelë WebM (kodek Vorbis)" +#: 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,9 +770,13 @@ msgstr "Kartelë WebM (kodek Vorbis)" msgid "Image for %(media_title)s" msgstr "Figurë për %(media_title)s" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" -msgstr "" +msgstr "Aktivizoni/Çaktivizoni Rrotullimin" #: mediagoblin/templates/mediagoblin/media_displays/stl.html:113 msgid "Perspective" @@ -770,14 +819,14 @@ 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 msgid "" "You can get a modern web browser that \n" " can play this video at \n" " http://getfirefox.com!" -msgstr "" +msgstr "Mund të merrni një shfletues web modern që \n është në gjendje ta shfaqë këtë video, te \n http://getfirefox.com!" #: mediagoblin/templates/mediagoblin/media_displays/video.html:69 msgid "WebM file (640p; VP8/Vorbis)" @@ -823,19 +872,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 "%(username)s's collections" -msgstr "" +msgstr "Koleksione të %(username)s" #: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19 #, python-format @@ -854,7 +903,7 @@ msgstr "Media nga %(username)s" msgid "" "%(username)s's media with tag %(tag)s" -msgstr "" +msgstr "Media të %(username)s me etiketën %(tag)s" #: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48 #, python-format @@ -866,30 +915,34 @@ msgstr "Media nga %(username)s" msgid "❖ Browsing media by %(username)s" msgstr "❖ Po shfletoni media nga %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "Shtoni një koment" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 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:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

Shtuar më

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +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 "Shtojeni “%(media_title)s” te një koleksion" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54 msgid "+" @@ -968,7 +1021,7 @@ 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 "" +msgstr "Shfletoni koleksionet" #: mediagoblin/templates/mediagoblin/user_pages/user.html:137 #, python-format @@ -993,11 +1046,11 @@ 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 @@ -1039,7 +1092,7 @@ msgstr "më të vjetra" 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." @@ -1069,9 +1122,33 @@ msgid "" " deleted." msgstr "Nuk duket se ka ndonjë faqe në këtë adresë. Na ndjeni!

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 "" + +#: 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 "Koment" #: mediagoblin/user_pages/forms.py:25 msgid "" @@ -1090,7 +1167,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 +1177,77 @@ msgstr "-- Përzgjidhni --" msgid "Include a note" msgstr "Përfshini një shënim" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "komentoi te postimi juaj" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 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:180 msgid "Your comment has been posted!" msgstr "Komenti juaj u postua!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 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:245 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:256 #, 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:262 #, 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:282 msgid "You deleted the media." msgstr "E fshitë median." -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 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:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "E fshitë koleksionin \"%s\"" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index f6918f71e5291daef2b73003f72cbf6b48e0bbac..5564d35d99671d3578fa01e2bb3125cc1bc7f7c4 100644 GIT binary patch delta 5072 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 uik#(6XY~Cmi&lBQ*WTUk?JTMx7?-2esf+lOIh;\n" "Language-Team: Serbian (http://www.transifex.com/projects/p/mediagoblin/language/sr/)\n" "MIME-Version: 1.0\n" @@ -18,34 +18,39 @@ 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." -msgstr "" - -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "" @@ -58,54 +63,54 @@ msgstr "" msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -116,7 +121,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -132,11 +137,11 @@ msgstr "" msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "" @@ -164,45 +169,45 @@ 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:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "" @@ -227,44 +232,63 @@ msgstr "" msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +296,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -344,7 +372,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -363,7 +391,7 @@ msgstr "" msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "" @@ -371,45 +399,45 @@ msgstr "" msgid "File" msgstr "" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -417,72 +445,25 @@ msgstr "" msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "" @@ -588,6 +569,53 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -600,13 +628,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -623,12 +651,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +677,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,7 +694,11 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -681,6 +723,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -705,6 +748,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -713,6 +757,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +768,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -821,7 +870,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 +913,27 @@ msgstr "" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1037,7 +1090,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1067,6 +1120,30 @@ msgid "" " 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 "" @@ -1098,73 +1175,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index 28ea51f840a925b2e1ddca5e96a9d693d539df79..3b961e60ab413b86b73d000536f403ffde032265 100644 GIT binary patch delta 5071 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 V$Jc7Ubm9M2^I~7~|FPyZ{{+Ox4|xCp delta 4238 zcma*odr*|u8OQOn3%K0neo?^{1TTm#AOsK$8V~~B8nGxz9Eom}Q7#o4Qe#-hiP~ve zp{$umGg{4POrtTAY|^o*WORa!NokE$YvLHR(deXFFR26R#I*hXe0QeJADt<)?B|^G zzVA8DdCocSb|1A39JYA|V*+0={N3Px4F4M(s{QBhLZmS%R6oP9_zk*n^hjeK#JM;M ze~NLq9~1Bh2IFb8;ROuGLA;FDG1nN6IT>Y4J`MJ0W2Rvt*5hiNfbZj0dbo~7)Z1dM z0ba)d>itL;<^)FIr>H=#A+ef!7=mFm>b`iS$z)n7-oY6B4ff&yj=(2LPZ~C1BIBEG3KQ{FREkbvC=MbY z^Ce&RS0&MyRO-RF9w(pze;L*B0BXR~$XMnoD!_aG>k&!DkVF%Qx-SzwffR};DDs)8 z0jiOYY2-_5yUE|a6SbyCP^mqRdj1S5@J~^D=qfU%2}rj38;x4ZV$>2nftqk@GWn-$ zdig3qA8Mw5MRoiYDzIVHi~@*8OOuRhAB&Zkg;TH%pT*sH4pT=n7!F|;E+x9@xEZyX z-yK8#3n`qZp%Y`->OaCBWK0uII<)&UQJbb5HS;Byj;l~>`8+bFIfRP$^!Dins;!;M4y47F5c+P;2)RZoz)kb2a0v0UK~O z_4TOC_Ms*+gbLh2)Lj^dWW;0kQc$W7Aidko`mt!bfJr~zt5bnZdxEHmg0gN7i(Rly-$5RNVVH7Im>8MSW zkD5UhIqEvdRBq3Y|1m;Te1g zQ%J`H*nnl&i!<;%ZomYh*oa+}_QW~FUb=;12>f2Erzlb4t2$hk;sEi%;`#b;j z0S|>zF8mokws9obbOHZTGZ~{jCo0e!)b$F~64YAl9@9xdsp&zbdxPhAKFlx;rXIj5r3Al}VJ}UBlRKPb; z0o_Htkb+pBkvJMPa27^mE-J8c)cd3k75HPA>Y=cjf;!lWif|_?katjPI)F;uSyTsC zPy>C5WAGoSH)ukc6|f7nlnYRq=|Ii+IUI|xBiq6J0X-TZaF(^U5va(bQ30f&W;)&9 zUW}F0=ipS_hRRGI4&mI{*3a!joM9LBSCIW|&LOV?6JBopCKO>O^>yXszmLKl8Z?79 zDy-fAq2Ft$nFr0W&UYMY#)UWv7o(P{6_w(rQ4@OJ?{@$7otQ-XKGekCLuLHz9FLW< z>ojPWhB7_v>Qq#!r=U`pgW5zhQ3Exg0%=DD@^jPx2T{)-N8NWCwOOyCGI<+Qa0nGZ zoTti)crxn2Jk$fTP)kvR6R{4r;6~Jgj)$#`q##*0vyc;OoiJv%697r%!($0t!Uxq|B8TU3XkHC9HPs6aDtIp*O$+>Q#gc&_z=S%JCKdvO8| zU>V-Udd#19|JT-Ix+#R|0xClNMy7)U>Cs&i^_J>hMLJgm3#DM5QSB5o0Ktskjk0BJU<+W0d7s zikj&z48l{m49}r5RZwf4u5#3#szSBT!)V4gk5bSkYC_H6$Eb6<2NmftRL6HvfexeY zi(72%{%nkvv!o{t5Fiw$A#w zt;EgL`!Nfvmsm^m6moLSFR%wMq8ryOwI=WhDx+Ux0;aL>nOKBuE3>?w{Kr!`Ktm25 zLp|_!jKP#gt(my+aq9C?nK_7d96)t^5<~DRI`B3sV_*CIr~i83W7e;2B$~90wlt^L z9(B;WC@Rr=A?h`U)7i2v)amqHDhjcAdt%%ftMg{gTDj7_(%I5nGK~rs^;gn5Gh^b) zhIaR)wvuVBzUmoic5gy_qxbXDWZ$lMr``K)VyyRCVvKiGQkl0a=^I~9a(uA&_v75Y zqO>RM-reIL_oZaKVDo*PS?ll>Om#c#4ej1z`AK7*bTd}tik4=xwq=#G<%jL2+1=q@ zXIj>-bbCt*j^yNJyQVvH3X5ISvt0!)SLnh8*^juNYHVw4Y0fSupkimPOE>Y!ce-4~ zF5jdFF53JPjP#Zl_5Rl+n{5C01bghh&r3_bGcn(-vM`&^KKs>R?;oq1eHAsGcJGOK dt9%RQzhd*nE_})1J6iYMnPoSw`Cl`u{x_>, 2011. -# , 2011, 2012. +# ingenman , 2011 +# joar , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" "Language-Team: Swedish (http://www.transifex.com/projects/p/mediagoblin/language/sv/)\n" "MIME-Version: 1.0\n" @@ -20,34 +20,39 @@ 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/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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "Användarnamn" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "Lösenord" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "E-postadress" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +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." @@ -60,54 +65,54 @@ msgstr "En användare med det användarnamnet finns redan." 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:182 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:188 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:206 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:214 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:227 msgid "Resent your verification email." msgstr "Skickade ett nytt verifierings-email." -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -118,7 +123,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -134,11 +139,11 @@ msgstr "Taggar" msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "Sökvägsnamn" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "Sökvägsnamnet kan inte vara tomt" @@ -166,45 +171,45 @@ 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." -msgstr "" - -#: mediagoblin/edit/forms.py:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "Tidigare lösenord" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "Ett inlägg med det sökvägsnamnet existerar redan." @@ -229,44 +234,63 @@ msgstr "Var försiktig, du redigerar en annan användares profil." 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:240 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "Fel lösenord" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +298,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -346,7 +374,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -365,7 +393,7 @@ msgstr "" msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "Ogiltig fil för mediatypen." @@ -373,45 +401,45 @@ msgstr "Ogiltig fil för mediatypen." msgid "File" msgstr "Fil" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Du måste ange en fil" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "Tjohoo! Upladdat!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "Verifiera din e-postadress" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -419,72 +447,25 @@ msgstr "" msgid "Media processing panel" msgstr "Mediabehandlingspanel" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "Lägg till media" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "Senast medier" @@ -590,6 +571,53 @@ 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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "Utforska" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +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 MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "Har du inte ett redan?" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -602,13 +630,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -625,12 +653,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +679,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,7 +696,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -683,6 +725,7 @@ 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/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -707,6 +750,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -715,6 +759,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +770,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -823,7 +872,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 +915,27 @@ msgstr "%(username)ss media" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1039,7 +1092,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1069,6 +1122,30 @@ msgid "" " 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 "" @@ -1100,73 +1177,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index 8cef459383aaa348f6779e6ccca69bb1c201d2fc..6e7ebd216781afefac95bdc7a98f7e47a1b7e9eb 100644 GIT binary patch delta 5165 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 LH-!8zYpwkkWM(#A diff --git a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po index 3586ee78..b0bf1aa1 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: -# వీవెన్ , 2011. +# వీవెన్ , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +19,39 @@ msgstr "" "Language: te\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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "వాడుకరి పేరు" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "సంకేతపదం" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "ఈమెయిలు చిరునామా" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "" @@ -59,54 +64,54 @@ msgstr "" msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -117,7 +122,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -133,11 +138,11 @@ msgstr "" msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "" @@ -165,45 +170,45 @@ 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:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "" @@ -228,44 +233,63 @@ msgstr "" msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +297,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -345,7 +373,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -364,7 +392,7 @@ msgstr "" msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "" @@ -372,45 +400,45 @@ msgstr "" msgid "File" msgstr "" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -418,72 +446,25 @@ msgstr "" msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "" @@ -589,6 +570,53 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -601,13 +629,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -624,12 +652,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +678,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,7 +695,11 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -682,6 +724,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -706,6 +749,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -714,6 +758,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +769,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -822,7 +871,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 +914,27 @@ msgstr "" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1038,7 +1091,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1068,6 +1121,30 @@ msgid "" " 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 "" @@ -1099,73 +1176,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index d75d2eb2bb80eae968af60f3890cdd98c4eb2cb7..c234ff007f8e3fad0648b3ec8d7d7b6de2712c6d 100644 GIT binary patch delta 5032 zcmeI!i&K=>8OQMhA|Rq73ZhYYCE^W5F5(5e;T13{RpW(5bY&OV0K0UTONoXxsYc@^ zX{2ei=AxrcHP+S))~KpbI!Z( zd(Ly7=bU~0@!^P1e-;tCk{I=>;pY+m`tmP6R=xlHeAUgEesmvVDn6EAOcoa4B&@|` z{1NuS_pv8lajt)c8ZxfCF%j4U<1q=Z8WS>UG;+8QnP^NN=HW=J!7|*A>v-~W97n&E z(KX=_?0{#HIm`#x1#cj~=2QN3#h4^xI$<*EJ_~zbHg;uxGo8jzE-b)~*y`M{#_4ax z(OiEMi|{;_V1J^>LoaIJw@?!u#LjpO72qi(c5?=|;bn}*=3d66F~4c0!LQlLAI3IE zaR{D83m>3T);onX;vi%UlZ`Q0grl$&`{P=C26v+tmfG8%uox9cDQcby3@P#!8X9N= zDzYs|Rm?Wj1N$)we~wz&`>2V|B6FC3plTn(A6-vF)w~c@f)dp8OHd0bNA0zmKIEUp zne|-IgFA3AokvUBN$Lvy!MFs3f4cv?hY!zx{>rthA)49GIXVO22!|?$= zi|KvI{{L6#QszaKAb`4|1@-xJsDZzSs{LMMOmhNN!mFr~eS*qJ zF{p`qqQ)76dcFinstLJhsD`UhDSs6e@h()YevR7I=TIrVf?DYfRH`ExU4f^do*&@! zM>>v0m8K9?%Gvk=HX+Z4%tIOqpa-)~!QrS>`%x>~iwfi@zKo|(8Cp2dPW@6;CYn(z ze+_m2>!^(ELyiBQbNw7D@M{>Q^Z!p88sMw&1$Jh-F^lLAz&+T4iad3Yecp>uo2V7T zHAkiLG-l%sEW_l%95MVBDg);+3a=q+Fn_~Y%x~fteL6108TdNtcw9#x>JaOc_)#la zhx2g<&cS=AfTj-PI|S=76BF6V78at$TY=naLXP_|#Nx~cG#20&xEkj$n!bY1;&S{N zb8z_xdk?f>IsI*@nm@n}7|pC&VI0O{H&h8y9EYJc;dsUe#LYy*?XmqfCnZ`&bY3LT#2| zsFjUGO;ms>ScZKt=v;pZRr3R=5*$W7|0~o&&Y+I#g(=iuE5FAD4H!Swe*b5nYB?X3 z2^aRp4LBNiqXNE&8u&UYu#ZqHyN4=e+%)@o0?wr07x^wTZhRJBnHI9&|J|nB@Bdq< zb6GOOPH7XS(%+A4bn_c*#VAH=!SA2~dx-t87aK&ID-X5uVtgDIV;ZhPW$G=A!DAsB zO7TgI#q$`AS5PT^*Hw#s=r!WeAs8k106R$>%vkSF%4x<7I z{f>re_z^1Q5o~Qm+zmBAE_TAnsFaqVR$7WmwGU%)4eI&LPJg@OZd7Rw;1E2DFW`sB z^C9D%Wd{&Kwt?A-O7%t5%6dLw2a=92)6YR==p-ujr%{=>j#_z#+4lXhsEj0`7C6|s zJ{cAGYz)8uD`;qd>hJ~r^N5S+Z^k`%6BYT!Ire!!gv06I#&FH&+NsP#eYcll89t8{ zco{omVW}P9Y*dElVfg*uM1y^2P9pou#D2p*9&^!0zZP{$E}~ZQ8P3P}dG`B%IVzx^ z;7+`Rnb^ur79Kzyx8LJX{Ma#R0r^ko!Xz5}8V`R~<1rkG1y35Y9BVKKe~a1!Ut>9T zTxi$ajUDI*P$g(W?TMAx9oIO19~0^CMJ?pLh0go`92Yd=?}W1V9VHC_wqxjs9b#vasw zZ{q|!RNnTNu7{E;{ee1HLxab?tifC785*=)ResZ!-K}@qiP3L&@CV}B>&N&a+V6B< z9~tF#d))1t3JM|R5aS=&-d`fa`YWU$wey^mwJW)?=DIo*L8QakZVvJ)WI6 zB4>=1otvLGYD89ER#sf;+!6CUP2Ql_?;A0VoaI|NS=qUK7QSz6eqQ^#qwYrhzqtPc H#Vz?4PF4Vy delta 4221 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 diff --git a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po index a5e95640..a7ee8db6 100644 --- a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po @@ -7,8 +7,8 @@ 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" "Language-Team: Chinese (Taiwan) (Big5) (http://www.transifex.com/projects/p/mediagoblin/language/zh_TW.Big5/)\n" "MIME-Version: 1.0\n" @@ -18,34 +18,39 @@ 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." -msgstr "" - -#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "" @@ -58,54 +63,54 @@ msgstr "" msgid "Sorry, a user with that email address already exists." msgstr "" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -116,7 +121,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -132,11 +137,11 @@ msgstr "" msgid "Separate tags by commas." msgstr "" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "" @@ -164,45 +169,45 @@ 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:67 -msgid "New password" -msgstr "" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "" @@ -227,44 +232,63 @@ msgstr "" msgid "Profile changes saved" msgstr "" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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,12 +296,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "" @@ -344,7 +372,7 @@ msgstr "" msgid "This field is required for public clients" msgstr "" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "" @@ -363,7 +391,7 @@ msgstr "" msgid "Add" msgstr "" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "" @@ -371,45 +399,45 @@ msgstr "" msgid "File" msgstr "" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -417,72 +445,25 @@ msgstr "" msgid "Media processing panel" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 MediaGoblin, an " -"extraordinarily great piece of media hosting software." -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 "" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "" @@ -588,6 +569,53 @@ msgid "" "%(verification_url)s" msgstr "" +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21 +#, python-format +msgid "" +"Powered by MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -600,13 +628,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "" @@ -623,12 +651,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +677,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,7 +694,11 @@ msgstr "" msgid "Changing %(username)s's account settings" msgstr "" -#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59 +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -681,6 +723,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34 #: mediagoblin/templates/mediagoblin/media_displays/audio.html:56 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -705,6 +748,7 @@ msgid "" msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "" @@ -713,6 +757,7 @@ msgstr "" msgid "WebM file (Vorbis codec)" 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,6 +768,10 @@ msgstr "" msgid "Image for %(media_title)s" msgstr "" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "" @@ -821,7 +870,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 +913,27 @@ msgstr "" msgid "❖ Browsing media by %(username)s" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 +#, python-format +msgid "%(formatted_time)s ago" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 -#, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 @@ -1037,7 +1090,7 @@ msgstr "" msgid "Tagged with" msgstr "" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "" @@ -1067,6 +1120,30 @@ msgid "" " 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 "" @@ -1098,73 +1175,77 @@ msgstr "" msgid "Include a note" msgstr "" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 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 index 3d267cfc45b089c04704cc1cc210d8293a819595..3fd4911a99e86185fd187bcdd36cff8778d4cfab 100644 GIT binary patch delta 5262 zcma*p3vg7`9mnyL@Yp2s2mum6NG<^a!H|$ZAPLVH2oVsFr{DuN*_&h~*$w+hSf#AB zf{4$$zM^QcVk>H=+I1AMEliop;MBni)X@sah+utBMWt1=-(T*nt!<~8fqc$6_ul_G z=YRfpH#a?%^3|@C__3_+cNu=Z;{Q22!((DaUdw!L_&w@5dW>@-wWYzme#g za2IyNgUB4_5cbBC$UpN}e)U1mKx5J|8+D(B{jn7LFu$2iqmY56*aJ7ZH(c-b@5M=s zKZtdB1m|Kdt0+f5D)3KG6FrIN;cnCdUqIGwUc^p3iaoI-$C!NPHydg2&pgC0Vw>l1 z3?4)a&!SQ`co1pC0wjhhMGw~DL|lZqxCyVu9jJ}v4R$8H2(^$!sCgPNu9e4VD9~2a z%I-i;#dM+`cpSUqZ&5qjhnnahGKcvPb@m>9X*?fw=GCYpn2UOTC2AvAqH1mJ5c1FF z%oYap;C391dr)V28kLDpkvUB6`OZ;PpcWiN1@1sCYy)a%TTn;&pgX<;=g@x=i|{P| z07nfa|F6<`nB~;tHI(`Vcnp=&3|5tgGq3_z<3_v}W0=E5E$qjrx8!kDaUDSI{3wpV z_c0$cEhkeGP#ahfr=b)tN2SbxEc^N_7ymvqw=2c@A&G7f=~mKGI436{t*f zpmu%_>i%u0jO;|kf8HHGj9T~!?5_9!a~cZpW!C_eIm(z7^oQdk7(=Z*ufTcV>rh3s z5xdSDmC6HHiYIXuW{>6-!*!?(9Kr5*0@;H(h4Yx-WDtEeF2`EjhI&2T!T{{%p z?c@erg4=Nco}@o#u7E+Cpdf)C;v z{2I$}%{Zq95_l#3PSly7#ctS>S+&CqOvApYBN*g57FC2(Q5#uUO#Uqz%?xP58?gsI zhg$I-_r^ESL;q7$fOFUfGkHiykcYZ|8nSt_3YXy~tiwNJ4UQbo8-UF?6St2i|5Iq3 zU|<6d;{Z3|eMmBl#kO@;^KlNg;T^aOZJam3shy`#sr@7B_4)!S1CzyvNEKG1b{s*~ z$StV&d*U>*XuOBo$ycb<4lQ>AUxNyCKPvF=P^o?m)A1-O<)={@dLMh@8B`{}a7~%y z^gXC}y;0A_C%TPFRKV#t4eRho3hyc^wU<{o3yLAfZ8~uV?#FEOR61`#E)Jw$iF$4! zDsBrB&a|UyVm%($`@fY2*)&&?Cl+fSK&9vquEHLi&-pyL23d>QFx8nLiQ4G_?1eA8 z9z|vJUAKSEHG^I0z8vh2BQZH}&oYJuIR69mgq z_pd_jv#0|7)C>ZDp5C9qt2)fyLRS|H@OB- zfugQAxjuxW8GjZP=Q!&5Q*Qqg)Wm;B&D;Az@~`44B(HkSW}<~Y)PtK)#dZe{!o8>( zcnvi{W{qPG>i%5R1Q)pD)3Go8*{J81q2k?)aok9`pc;C9r)e(8?yK^?&XOv68+7INJ66za@Bz|ELGx2qpFx6@DxpFob) z>_-aQWXy8{&P6R?1#U$f75HP+0zOA5RdL>q!yNSOK>6M?bv`XpcXuqL0O6x zR$wLbo0V!{!u2K8Tj5#c{2`KyT5-GU&8Yi->iPz%sIo8N&o->Y(RdVf#yu8085)g+ z^sBH8ec1K=e-DkN4EzQgF>8tQbsR$-#ZJ@%e?jeFC^s*|5!ef3sPWCNw_soTcVa)> zfjWX`Tn}Ov{dbm z@RH@mOu(S)!>G)?>h}AsApg2yHh=J~!x(PD_i!w(yVQ9bwxI&<#Tqm#9cQ6McMIzN zou~yLMjgS&sQ82UCe!$QEX8KjcgKBk8cM|;)LFfPK0JeCaOGvr_w{wC06Vc8{vOZ6 z1K1sppfdEj>j_jQ-@$bJ(Df`9&`-VGeOn6MMlts0!UUX()t4t;@ALG)#$c$`8;RJy z)e(QIT^P2!O+k|=?K?QpI;l@0*>_udFqC0+{Ur8I%1JDmT$X$!GcP6ie!nfL-F-gW zmkbSzK_`EUGXfx_>2nI|uu}n*_$qGgzrqv&aMr_j>3`Cku!0xa^ zCfMTRcQg>>=60)*HTd({L?md1qJbhNwj0)3dcM)$Vw(=zUTb2uH}T?xUze7TE1PVU zPN*uMIBtCT`0*Kw7LHqNxBJ8XU|`%V@>pe+jW3&13POMv8)9eq}VcQzB z)a&o?1`4e)&5=l3RY^%lM@MlavxMVKTG4Hs$|T)~$(x%)o44dUN^D`Q5b{O3b)){yzYl#Z|Zf delta 4360 zcmZ|QdvuLg8prXSghWJ0Lav14l8_LRkVqnuD2ZEyDOI#uAqQE=Q8BG?JC-G4CDZE4 zt4zw2s#`IN({_l=EFE-inbiyJ49hTU$fZ-IE@ftwG2fr}oteLymE^Pce)r|s&))Aj z|32YYd(6*!C8FIMhMyb!_26%HkZS+`x!l>9c&dNJUidwxV)rh_ z#142K{qQn&!Ygx8AX5lPci2d;lRx`ubm`%O1tG&Q4Fo615 zWD4^;48@D6Kw6Pl%|i^v5E|7l5@|At*qQZB4uvEd#ybxxu|4%_%*0o59G=Aq7#e8@ zJOef1Yp4ZwVhFyA3hV=nz>`>yO&EytNlzbKg3+vRUZ*es51>-?8Fs`g$glZ|e@{*& z+L)fyJK##}j|zM@YT_o;g6EO7ObaT&htBiR7-LAH>4xf;h~9P-vMDI?Jk$ackY7{I zKb`G*r~T)sGi^kr_8e;b1ytY{QFo{XS+Vgcs9c2#ch~}a;yfl{lQ#SSd%S0b) zr~g1rdfi)!zMV{sr3!b)6&yYSE0vpb97eH@50iEbEHp)PYn5AvTy z;SvpNu`5^oCs>E9X*!V(-Tp+>r5S_T`3&rf3s7fSi>zsmpf>P(REj@CW$ZfYh`w>2 z-*cWn^it5oT?j{K-4_*E4*zs^vruQY2$hjFs8p{qCcmtWs+{TF*nP^NQmSPd^ zN8S3HSb-t^?c2W+6?h#^#Y0$vk5Pe?5Z&9XZ&pzljPbn8E-Xe(xCHq%HIDBiF_j?%2~@u?FbHp=#^1-z7@T6?u^3eUOe9t_HHG{?Lt!lqv05L!qpf>6jf*;n=-Mf_7N50SnB0ihsV&3W76!qbr6-&KcL>0duimKV>2P- zD+kk2J6VGCF&j|}oWKaYj(S@jpi&w+)Sh@b`cvP6ns^%q;}KLwPM|V&+VNxOd6SpI zNFIENTl{z}_;^x^-p#Nl{uoJ$X~BH#mTBMKX&6b}gX&*}T5vZqjX8|rcm%)2(@4zb z7-?lHa~-uoZ(Npr`-@RK-H+Xw;XE?N+{(5WN+dmj)N`>Dj&_`a%FJx1zSMDzV-0rY z`8HI)L#QM8wf)>{+9+t^?~vm%5Ai8X;lLH)QsfOayHN}O7PZq0sBu@E_GZ)qcd#DY z=i1MAVgmJjsOL?n0Ip&uz5l`FzatG%sI%>jIIl9=O&pSE z_wR{%o`X7qQK-PDI_+~D7ht5`{|XgwgX5dnpZZbMM1Mg|aMh{bKrMI|6<{D2BMSRq zU(7}q&PI(}i@HO#7=tHKNBcQ?wLoxzy-*lxKs0KBeyHceu?yy*29}^EtU@pP@EQ&s z#f8LZ&QF=DMjhcX?2Xq@?|pmT@wJ#bn&BGo9u0BWYm6OX4k`mvQ30$%?QA{v#C_NY z&pFTAPyyd^>i&iHxM0*#hM_hP<2V4-KdX@NHSt8J!Q*sTk6O46b=m5%2fl+!;b~ML z7g0O=r_&x+WM^=wV*!Tpd=hG&=TPI^sDL(jod;V`secOt@sQ(j)ES?|jrfIAe}1f; zu@y*GjfEVi`4Tlx6d$KrxG&aV8U|t`YT+}e40z8|(0~@lyQm$S@pi{p)a6V)nd(7V*dlcLC z>8RWOI_mp=KPte-j**k>eghrdsJpTg-@)Htf1F>UqvQNvqo7nA#Uwm~>G%yMpo?(z zbz6k&CR8zJE;IR6AuQsQM2|;qQK?^mT4(cg@~@qop&<>g zqAp7~2OEKzsMl*emf<2CfS+Oj{tGq!5r$yw3_BwU7)*VTV{Syygxalzv9!JcIc@_c887x_86?Q9ihughxQap0?U_08*QTR%MBdZ_;TiJIn9 z4XuZ2n@{-K>UZW2DgE!BweOZqTU&ni-jgJdqRGh&ZmT}n{L5plZ*I8W*wC`$)#myG z|C_=!$z4`nI@U9Hae0OHC_Kfg%lRaUBsSOVYOdPbvTbk64i@;qtiCWJ+TXWo1JA`L nK1pfwj;*bG8cb{bspjei)3W{jmaRvLRi(B~HI%IM=ZpUX, 2011. -# Harry Chen , 2011-2012. -# , 2012. +# , 2011 +# Harry Chen , 2011-2012 +# medicalwei , 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" +"POT-Creation-Date: 2013-05-27 13:54-0500\n" +"PO-Revision-Date: 2013-05-27 18:54+0000\n" "Last-Translator: cwebber \n" -"Language-Team: LANGUAGE \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,34 +21,39 @@ 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/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/auth/forms.py:52 mediagoblin/auth/forms.py:67 +#: mediagoblin/auth/forms.py:26 msgid "Username" msgstr "使用者名稱" -#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71 +#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45 +#: mediagoblin/tests/test_util.py:110 msgid "Password" msgstr "密碼" -#: mediagoblin/auth/forms.py:60 +#: mediagoblin/auth/forms.py:34 msgid "Email address" msgstr "Email 位址" -#: mediagoblin/auth/forms.py:78 +#: mediagoblin/auth/forms.py:41 +msgid "Username or Email" +msgstr "" + +#: mediagoblin/auth/forms.py:52 msgid "Username or email" msgstr "使用者名稱或 email" +#: mediagoblin/auth/tools.py:31 +msgid "Invalid User name or email address." +msgstr "" + +#: mediagoblin/auth/tools.py:32 +msgid "This field does not take email addresses." +msgstr "" + +#: mediagoblin/auth/tools.py:33 +msgid "This field requires an email address." +msgstr "" + #: mediagoblin/auth/views.py:54 msgid "Sorry, registration is disabled on this instance." msgstr "抱歉,本站已經暫停註冊。" @@ -61,54 +66,54 @@ msgstr "抱歉,這個使用者名稱已經存在。" msgid "Sorry, a user with that email address already exists." msgstr "抱歉,此 email 位置已經被註冊了。" -#: mediagoblin/auth/views.py:174 +#: mediagoblin/auth/views.py:182 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:188 msgid "The verification key or user id is incorrect" msgstr "認證碼或是使用者 ID 錯誤" -#: mediagoblin/auth/views.py:198 +#: mediagoblin/auth/views.py:206 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:214 msgid "You've already verified your email address!" msgstr "您的電子郵件已經確認了!" -#: mediagoblin/auth/views.py:219 +#: mediagoblin/auth/views.py:227 msgid "Resent your verification email." msgstr "重送認證信。" -#: mediagoblin/auth/views.py:250 +#: mediagoblin/auth/views.py:258 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 +#: mediagoblin/auth/views.py:269 msgid "Couldn't find someone with that username." msgstr "" -#: mediagoblin/auth/views.py:264 +#: mediagoblin/auth/views.py:272 msgid "" "An email has been sent with instructions on how to change your password." msgstr "修改密碼的指示已經由電子郵件寄送到您的信箱。" -#: mediagoblin/auth/views.py:271 +#: mediagoblin/auth/views.py:279 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 +#: mediagoblin/auth/views.py:336 msgid "You can now log in using your new password." msgstr "您現在可以用新的密碼登入了!" -#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93 +#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82 #: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47 #: mediagoblin/user_pages/forms.py:45 msgid "Title" @@ -119,7 +124,7 @@ 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/edit/forms.py:86 mediagoblin/submit/forms.py:32 #: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49 msgid "" "You can use\n" @@ -135,11 +140,11 @@ msgstr "標籤" msgid "Separate tags by commas." msgstr "用逗號分隔標籤。" -#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101 +#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90 msgid "Slug" msgstr "簡稱" -#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102 +#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91 msgid "The slug can't be empty" msgstr "簡稱不能為空白" @@ -167,45 +172,45 @@ 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:67 -msgid "New password" -msgstr "新密碼" - -#: mediagoblin/edit/forms.py:74 msgid "License preference" msgstr "" -#: mediagoblin/edit/forms.py:80 +#: mediagoblin/edit/forms.py:69 msgid "This will be your default license on upload forms." msgstr "" -#: mediagoblin/edit/forms.py:82 +#: mediagoblin/edit/forms.py:71 msgid "Email me when others comment on my media" msgstr "當有人對我的媒體評論時寄信給我" -#: mediagoblin/edit/forms.py:94 +#: mediagoblin/edit/forms.py:83 msgid "The title can't be empty" msgstr "標題不能是空的" -#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50 +#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50 #: mediagoblin/user_pages/forms.py:48 msgid "Description of this collection" msgstr "這個蒐藏的描述" -#: mediagoblin/edit/forms.py:103 +#: mediagoblin/edit/forms.py:92 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:99 +msgid "Old password" +msgstr "舊的密碼" + +#: mediagoblin/edit/forms.py:101 +msgid "Enter your old password to prove you own this account." +msgstr "輸入您的舊密碼來證明您擁有這個帳號。" + +#: mediagoblin/edit/forms.py:104 +msgid "New password" +msgstr "新密碼" + +#: mediagoblin/edit/views.py:67 msgid "An entry with that slug already exists for this user." msgstr "這個簡稱已經被其他人用了" @@ -230,44 +235,63 @@ msgstr "您正在修改別人的個人檔案,請小心操作。" msgid "Profile changes saved" msgstr "個人檔案修改已儲存" -#: mediagoblin/edit/views.py:241 -msgid "Wrong password" -msgstr "密碼錯誤" - -#: mediagoblin/edit/views.py:252 +#: mediagoblin/edit/views.py:240 msgid "Account settings saved" msgstr "帳號設定已儲存" -#: mediagoblin/edit/views.py:286 +#: mediagoblin/edit/views.py:274 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:310 mediagoblin/submit/views.py:138 +#: mediagoblin/user_pages/views.py:222 #, python-format msgid "You already have a collection called \"%s\"!" msgstr "您已經有一個稱做「%s」的蒐藏了!" -#: mediagoblin/edit/views.py:326 +#: mediagoblin/edit/views.py:314 msgid "A collection with that slug already exists for this user." msgstr "這個使用者已經有使用該簡稱的蒐藏了。" -#: mediagoblin/edit/views.py:343 +#: mediagoblin/edit/views.py:329 msgid "You are editing another user's collection. Proceed with caution." msgstr "您正在修改別人的蒐藏,請小心操作。" -#: mediagoblin/gmg_commands/theme.py:58 +#: mediagoblin/edit/views.py:348 +msgid "Wrong password" +msgstr "密碼錯誤" + +#: mediagoblin/edit/views.py:363 +msgid "Your password was changed successfully" +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 " @@ -275,12 +299,16 @@ msgid "" "domain." msgstr "" -#: mediagoblin/media_types/__init__.py:61 -#: mediagoblin/media_types/__init__.py:102 +#: mediagoblin/media_types/__init__.py:111 +#: mediagoblin/media_types/__init__.py:155 msgid "Sorry, I don't support that file type :(" msgstr "抱歉,我不支援這樣的檔案格式 :(" -#: mediagoblin/media_types/video/processing.py:36 +#: mediagoblin/media_types/pdf/processing.py:136 +msgid "unoconv failing to run, check log file" +msgstr "" + +#: mediagoblin/media_types/video/processing.py:37 msgid "Video transcoding failed" msgstr "影像轉碼失敗" @@ -347,7 +375,7 @@ msgstr "此應用程式的重定向 URI,本欄位在公開類型的 OAuth clie msgid "This field is required for public clients" msgstr "本欄位在公開類型的 OAuth client 為必填" -#: mediagoblin/plugins/oauth/views.py:59 +#: mediagoblin/plugins/oauth/views.py:56 msgid "The client {0} has been registered!" msgstr "OAuth client {0} 註冊完成!" @@ -366,7 +394,7 @@ msgstr "" msgid "Add" msgstr "增加" -#: mediagoblin/processing/__init__.py:172 +#: mediagoblin/processing/__init__.py:193 msgid "Invalid file given for media type." msgstr "指定錯誤的媒體類別!" @@ -374,45 +402,45 @@ msgstr "指定錯誤的媒體類別!" msgid "File" msgstr "檔案" -#: mediagoblin/submit/views.py:51 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "您必須提供一個檔案" -#: mediagoblin/submit/views.py:97 +#: mediagoblin/submit/views.py:93 msgid "Woohoo! Submitted!" msgstr "啊哈!PO 上去啦!" -#: mediagoblin/submit/views.py:146 +#: mediagoblin/submit/views.py:144 #, python-format msgid "Collection \"%s\" added!" msgstr "蒐藏「%s」新增完成!" -#: mediagoblin/templates/mediagoblin/base.html:64 +#: mediagoblin/templates/mediagoblin/base.html:67 msgid "Verify your email!" msgstr "確認您的電子郵件" -#: mediagoblin/templates/mediagoblin/base.html:65 +#: mediagoblin/templates/mediagoblin/base.html:68 msgid "log out" msgstr "登出" -#: mediagoblin/templates/mediagoblin/base.html:70 +#: mediagoblin/templates/mediagoblin/base.html:73 #: 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:82 #, python-format msgid "%(user_name)s's account" msgstr "%(user_name)s 的帳號" -#: mediagoblin/templates/mediagoblin/base.html:86 +#: mediagoblin/templates/mediagoblin/base.html:89 msgid "Change account settings" msgstr "更改帳號設定" -#: mediagoblin/templates/mediagoblin/base.html:90 -#: mediagoblin/templates/mediagoblin/base.html:105 +#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:108 #: mediagoblin/templates/mediagoblin/admin/panel.html:21 #: mediagoblin/templates/mediagoblin/admin/panel.html:26 #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21 @@ -420,72 +448,25 @@ msgstr "更改帳號設定" msgid "Media processing panel" msgstr "媒體處理面板" -#: mediagoblin/templates/mediagoblin/base.html:93 +#: mediagoblin/templates/mediagoblin/base.html:96 msgid "Log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:96 +#: mediagoblin/templates/mediagoblin/base.html:99 #: mediagoblin/templates/mediagoblin/user_pages/user.html:156 msgid "Add media" msgstr "新增媒體" -#: mediagoblin/templates/mediagoblin/base.html:99 +#: mediagoblin/templates/mediagoblin/base.html:102 #: 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 MediaGoblin, a GNU project." -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:125 -#, python-format -msgid "" -"Released under the AGPL. Source code available." -msgstr "以 AGPL 授權釋出。備有原始碼。" - #: mediagoblin/templates/mediagoblin/error.html:24 msgid "Image of goblin stressing out" 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 站台! " - -#: mediagoblin/templates/mediagoblin/root.html:35 -msgid "" -"This site is running MediaGoblin, an " -"extraordinarily great piece of media hosting software." -msgstr "本站使用 MediaGoblin — 與眾不同的媒體分享網站。" - -#: 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 帳號以進行上傳媒體、張貼評論等等。" - -#: 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 "" -"Create an account at this site\n" -" or\n" -" Set up MediaGoblin on your own server" -msgstr "在這個網站上建立帳號\n 或是\n 在自己的伺服器上建立 MediaGoblin" - -#: mediagoblin/templates/mediagoblin/root.html:47 +#: mediagoblin/templates/mediagoblin/root.html:32 msgid "Most recent media" msgstr "最新的媒體" @@ -591,6 +572,53 @@ msgid "" "%(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 MediaGoblin, a GNU project." +msgstr "" + +#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24 +#, python-format +msgid "" +"Released under the AGPL. Source code available." +msgstr "以 AGPL 授權釋出。備有原始碼。" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20 +msgid "Explore" +msgstr "探索" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22 +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "嘿!歡迎來到 MediaGoblin 站台! " + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24 +msgid "" +"This site is running MediaGoblin, an " +"extraordinarily great piece of media hosting software." +msgstr "本站使用 MediaGoblin — 與眾不同的媒體分享網站。" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25 +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:27 +msgid "Don't have one yet? It's easy!" +msgstr "沒有帳號嗎?開帳號很簡單!" + +#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28 +#, python-format +msgid "" +"Create an account at this site\n" +" or\n" +" Set up MediaGoblin on your own server" +msgstr "" + #: mediagoblin/templates/mediagoblin/bits/logo.html:23 #: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23 msgid "MediaGoblin logo" @@ -603,13 +631,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:182 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:198 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:204 msgid "Add attachment" msgstr "新增附件" @@ -626,12 +654,22 @@ 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:55 #: 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_pass.html:28 +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38 +#, python-format +msgid "Changing %(username)s's password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45 +msgid "Save" +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 +680,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 "永久刪除" @@ -659,7 +697,11 @@ 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:46 +msgid "Change your password." +msgstr "" + +#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62 msgid "Delete my account" msgstr "" @@ -684,6 +726,7 @@ msgstr "此媒體被 tag 成:%(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:65 #: mediagoblin/templates/mediagoblin/media_displays/stl.html:136 #: mediagoblin/templates/mediagoblin/media_displays/video.html:55 msgid "Download" @@ -708,6 +751,7 @@ msgid "" msgstr "您可以在 http://getfirefox.com 取得可以播放此聲音的瀏覽器!" #: mediagoblin/templates/mediagoblin/media_displays/audio.html:60 +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71 #: mediagoblin/templates/mediagoblin/media_displays/video.html:61 msgid "Original file" msgstr "原始檔案" @@ -716,6 +760,7 @@ msgstr "原始檔案" msgid "WebM file (Vorbis codec)" msgstr "WebM 檔案 (Vorbis 編碼)" +#: 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,6 +771,10 @@ msgstr "WebM 檔案 (Vorbis 編碼)" msgid "Image for %(media_title)s" msgstr " %(media_title)s 的照片" +#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79 +msgid "PDF file" +msgstr "" + #: mediagoblin/templates/mediagoblin/media_displays/stl.html:112 msgid "Toggle Rotate" msgstr "切換旋轉" @@ -824,7 +873,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 "移除" @@ -867,24 +916,28 @@ msgstr "%(username)s 的媒體" msgid "❖ Browsing media by %(username)s" msgstr "❖ 瀏覽 %(username)s 的媒體" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:94 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:95 msgid "Add a comment" msgstr "新增評論" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:104 msgid "Add this comment" msgstr "增加評論" -#: mediagoblin/templates/mediagoblin/user_pages/media.html:123 -msgid "at" -msgstr "在" - -#: mediagoblin/templates/mediagoblin/user_pages/media.html:144 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:132 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:152 +#: mediagoblin/templates/mediagoblin/user_pages/media.html:164 #, python-format -msgid "" -"

Added on

\n" -"

%(date)s

" -msgstr "

加入日期

\n

%(date)s

" +msgid "%(formatted_time)s ago" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:150 +msgid "Added" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:161 +msgid "Created" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28 #: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40 @@ -1040,7 +1093,7 @@ msgstr "更舊的" msgid "Tagged with" msgstr "標籤" -#: mediagoblin/tools/exif.py:80 +#: mediagoblin/tools/exif.py:83 msgid "Could not read the image file." msgstr "無法讀取圖片檔案。" @@ -1070,6 +1123,30 @@ msgid "" " 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 "" @@ -1101,73 +1178,77 @@ msgstr "— 請選擇 —" msgid "Include a note" msgstr "加註" -#: mediagoblin/user_pages/lib.py:56 +#: mediagoblin/user_pages/lib.py:58 msgid "commented on your post" msgstr "在您的內容張貼評論" -#: mediagoblin/user_pages/views.py:166 +#: mediagoblin/user_pages/views.py:169 +msgid "Sorry, comments are disabled." +msgstr "" + +#: mediagoblin/user_pages/views.py:174 msgid "Oops, your comment was empty." msgstr "啊,您的留言是空的。" -#: mediagoblin/user_pages/views.py:172 +#: mediagoblin/user_pages/views.py:180 msgid "Your comment has been posted!" msgstr "您的留言已經張貼完成!" -#: mediagoblin/user_pages/views.py:197 +#: mediagoblin/user_pages/views.py:205 msgid "Please check your entries and try again." msgstr "請檢查項目並重試。" -#: mediagoblin/user_pages/views.py:237 +#: mediagoblin/user_pages/views.py:245 msgid "You have to select or add a collection" msgstr "您需要選擇或是新增一個蒐藏" -#: mediagoblin/user_pages/views.py:248 +#: mediagoblin/user_pages/views.py:256 #, python-format msgid "\"%s\" already in collection \"%s\"" msgstr "「%s」已經在「%s」蒐藏" -#: mediagoblin/user_pages/views.py:264 +#: mediagoblin/user_pages/views.py:262 #, python-format msgid "\"%s\" added to collection \"%s\"" msgstr "「%s」加入「%s」蒐藏" -#: mediagoblin/user_pages/views.py:286 +#: mediagoblin/user_pages/views.py:282 msgid "You deleted the media." msgstr "您已經刪除此媒體。" -#: mediagoblin/user_pages/views.py:293 +#: mediagoblin/user_pages/views.py:289 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:296 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:370 msgid "You deleted the item from the collection." msgstr "您已經從該蒐藏中刪除該項目。" -#: mediagoblin/user_pages/views.py:379 +#: mediagoblin/user_pages/views.py:374 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:382 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:415 #, python-format msgid "You deleted the collection \"%s\"" msgstr "您已經刪除「%s」蒐藏。" -#: mediagoblin/user_pages/views.py:429 +#: mediagoblin/user_pages/views.py:422 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:430 msgid "" "You are about to delete another user's collection. Proceed with caution." msgstr "您正在刪除別人的蒐藏,請小心操作。" From b85d9e9567984578ba549165edf721d67a83fa66 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 28 May 2013 09:05:05 -0700 Subject: [PATCH 053/153] cleanup --- mediagoblin/auth/tools.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 48e0d572..40dcf59e 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -15,9 +15,7 @@ # along with this program. If not, see . import logging - import wtforms -from sqlalchemy import or_ from mediagoblin import mg_globals from mediagoblin.db.models import User @@ -30,12 +28,6 @@ from mediagoblin import auth _log = logging.getLogger(__name__) -_log = logging.getLogger(__name__) - -_log = logging.getLogger(__name__) - -_log = logging.getLogger(__name__) - def normalize_user_or_email_field(allow_email=True, allow_user=True): """ From d90f44d2a4de37bc5bd487a2a725fdcb75df4d27 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 28 May 2013 09:28:59 -0700 Subject: [PATCH 054/153] cleanup --- mediagoblin/auth/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index adcf07fe..22da54d0 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -21,8 +21,8 @@ from mediagoblin import mg_globals from mediagoblin.db.models import User from mediagoblin.tools.mail import (normalize_email, send_email, email_debug_message) -from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ 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 From d1c9ef47c43d33f265d93ef2ded23fcbb9213999 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 28 May 2013 09:56:16 -0700 Subject: [PATCH 055/153] removed extra argument from check_login_simple in login view --- mediagoblin/auth/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index fa84bbb1..22120d10 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -100,7 +100,7 @@ def login(request): username = login_form.data['username'] if login_form.validate(): - user = check_login_simple(username, login_form.password.data, True) + user = check_login_simple(username, login_form.password.data) if user: # set up login in session From f670f48ddd047f09566e196f86f6253412f801cd Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 29 May 2013 13:13:50 -0700 Subject: [PATCH 056/153] form is already validated, no need to validate again --- mediagoblin/edit/views.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 249fb8ba..4c4e5131 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -230,13 +230,9 @@ def edit_account(request): license_preference=user.license_preference) if request.method == 'POST' and form.validate(): - if form.wants_comment_notification.validate(form): - user.wants_comment_notification = \ - form.wants_comment_notification.data + user.wants_comment_notification = form.wants_comment_notification.data - if form.license_preference.validate(form): - user.license_preference = \ - form.license_preference.data + user.license_preference = form.license_preference.data if form.new_email.data: if not form.password.data: From a90b350f718baf96c66c57fac2a5e7b0e97f7efd Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 29 May 2013 13:19:36 -0700 Subject: [PATCH 057/153] send_verification_email was moved to auth/tools --- mediagoblin/edit/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 4c4e5131..df7db21b 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -24,6 +24,7 @@ from mediagoblin import messages from mediagoblin import mg_globals from mediagoblin.auth import lib as auth_lib +from mediagoblin.auth import tools as auth_tools from mediagoblin.auth.views import email_debug_message from mediagoblin.edit import forms from mediagoblin.edit.lib import may_edit_media @@ -265,7 +266,7 @@ def edit_account(request): verification_key=verification_key)}) email_debug_message(request) - auth_lib.send_verification_email(user, request, new_email, + auth_tools.send_verification_email(user, request, new_email, rendered_email) if not form.errors: From 342f06f7bd40ee47a48562b42006225e93f0c386 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 22 May 2013 14:51:30 -0700 Subject: [PATCH 058/153] modified verification emails to use itsdangerous tokens --- mediagoblin/auth/forms.py | 3 -- mediagoblin/auth/lib.py | 15 +++--- mediagoblin/auth/tools.py | 13 ++--- mediagoblin/auth/views.py | 95 ++++++++++++++++++++++------------ mediagoblin/db/migrations.py | 20 +++++++ mediagoblin/db/models.py | 3 -- mediagoblin/tests/test_auth.py | 44 ++++------------ 7 files changed, 107 insertions(+), 86 deletions(-) diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 0a391d67..ec395d60 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -58,9 +58,6 @@ class ChangePassForm(wtforms.Form): 'Password', [wtforms.validators.Required(), wtforms.validators.Length(min=5, max=1024)]) - userid = wtforms.HiddenField( - '', - [wtforms.validators.Required()]) token = wtforms.HiddenField( '', [wtforms.validators.Required()]) diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index bfc36b28..0810bd1b 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -20,6 +20,7 @@ import bcrypt from mediagoblin.tools.mail import send_email from mediagoblin.tools.template import render_template +from mediagoblin.tools.crypto import get_timed_signer_url from mediagoblin import mg_globals @@ -91,8 +92,8 @@ def fake_login_attempt(): 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): @@ -103,14 +104,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', {'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.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/auth/tools.py b/mediagoblin/auth/tools.py index d86235b1..d17ee4e6 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -62,8 +62,8 @@ def normalize_user_or_email_field(allow_email=True, allow_user=True): EMAIL_VERIFICATION_TEMPLATE = ( - u"http://{host}{uri}?" - u"userid={userid}&token={verification_key}") + u"{uri}?" + u"token={verification_key}") def send_verification_email(user, request, email=None, @@ -79,14 +79,15 @@ def send_verification_email(user, request, email=None, 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( - host=request.host, - uri=request.urlgen('mediagoblin.auth.verify_email'), - userid=unicode(user.id), - verification_key=user.verification_key)}) + uri=request.urlgen('mediagoblin.auth.verify_email', + qualified=True), + verification_key=verification_key)}) # TODO: There is no error handling in place send_email( diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index bb7bda77..45cb3a54 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -15,10 +15,11 @@ # along with this program. If not, see . import uuid -import datetime +from itsdangerous import BadSignature from mediagoblin import messages, mg_globals from mediagoblin.db.models import User +from mediagoblin.tools.crypto import get_timed_signer_url from mediagoblin.tools.response import render_to_response, redirect, render_404 from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools.mail import email_debug_message @@ -115,16 +116,28 @@ 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']): + return redirect( + request, + 'index') + + user = User.query.filter_by(id=int(token)).first() + + if user and user.email_verified is False: user.status = u'active' user.email_verified = True - user.verification_key = None - user.save() messages.add_message( @@ -166,9 +179,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) @@ -235,11 +245,6 @@ def forgot_password(request): # 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) @@ -254,31 +259,44 @@ def verify_forgot_password(request): """ # get form data variables, and specifically check for presence of token formdata = _process_for_token(request) - if not formdata['has_userid_and_token']: + if not formdata['has_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) + # 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.')) - # 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')): + 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.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( @@ -292,10 +310,20 @@ def verify_forgot_password(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) + 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 accoutn.')) + + return redirect( + request, 'index') def _process_for_token(request): @@ -313,7 +341,6 @@ def _process_for_token(request): formdata = { 'vars': formdata_vars, - 'has_userid_and_token': - 'userid' in formdata_vars and 'token' in formdata_vars} + 'has_token': 'token' in formdata_vars} return formdata diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 2c553396..6c9bf5cc 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -287,3 +287,23 @@ 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() diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 2b925983..f5470cb9 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -68,12 +68,9 @@ class User(Base, UserMixin): # set to nullable=True implicitly. wants_comment_notification = 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) ## TODO # plugin data would be in a separate model diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index 755727f9..48b148dd 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -156,20 +156,15 @@ 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( @@ -233,35 +228,17 @@ def test_register_views(test_app): 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() @@ -272,7 +249,6 @@ def test_register_views(test_app): template.clear_test_template_context() response = test_app.post( '/auth/forgot_password/verify/', { - 'userid': parsed_get_params['userid'], 'password': 'iamveryveryhappy', 'token': parsed_get_params['token']}) response.follow() From 69b888c22c326b1e69ee8e050a415561b6ca6aac Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 28 May 2013 10:43:57 -0700 Subject: [PATCH 059/153] cleanup after merge --- mediagoblin/auth/tools.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index d17ee4e6..c45944d3 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -22,6 +22,7 @@ from sqlalchemy import or_ from mediagoblin import mg_globals from mediagoblin.auth import lib as auth_lib +from mediagoblin.tools.crypto import get_timed_signer_url from mediagoblin.db.models import User from mediagoblin.tools.mail import (normalize_email, send_email, email_debug_message) From 1bce0c15ba97995ba7772296ab698b36a7dc41ca Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 4 Jun 2013 07:58:17 -0700 Subject: [PATCH 060/153] minor changes from aaronw's review --- mediagoblin/app.py | 2 ++ .../templates/mediagoblin/bits/frontpage_welcome.html | 10 +++++----- .../templates/mediagoblin/user_pages/media.html | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 982e570c..ecd3de0e 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -100,6 +100,8 @@ class MediaGoblinApp(object): # 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() diff --git a/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html b/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html index 26153694..9ef28a4d 100644 --- a/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html +++ b/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html @@ -22,17 +22,17 @@

{% trans %}Hi there, welcome to this MediaGoblin site!{% endtrans %}

{% trans %}This site is running MediaGoblin, an extraordinarily great piece of media hosting software.{% endtrans %}

- {% if auth %} + {% if auth %}

{% trans %}To add your own media, place comments, and more, you can log in with your MediaGoblin account.{% endtrans %}

{% if allow_registration %}

{% trans %}Don't have one yet? It's easy!{% endtrans %}

{% trans register_url=request.urlgen('mediagoblin.auth.register') -%} Create an account at this site or - {%- endtrans %} - {% endif %} - {% endif %} - {% trans %} + {%- endtrans %} + {% endif %} + {% endif %} + {% trans %} Set up MediaGoblin on your own server {%- endtrans %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 5420752f..fb892fd7 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -86,7 +86,7 @@

{{ media.description_html }}

{% endautoescape %} {% if comments %} - {% if app_config['allow_comments'] and auth %} + {% if app_config['allow_comments'] %} Date: Tue, 4 Jun 2013 11:26:34 -0700 Subject: [PATCH 061/153] fixed a bug that was deleting the messages --- mediagoblin/app.py | 4 ++-- mediagoblin/auth/tools.py | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mediagoblin/app.py b/mediagoblin/app.py index ecd3de0e..575a3835 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -192,11 +192,11 @@ class MediaGoblinApp(object): request.urlgen = build_proxy - mg_request.setup_user_in_request(request) - # Log user out if in no_auth mode 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) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 22da54d0..ae0b79da 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -202,6 +202,7 @@ def check_auth_enabled(): def no_auth_logout(request): - """Log out the user if in no_auth mode""" - if not mg_globals.app.auth: - request.session.delete() + """Log out the user if in no_auth mode, 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() From dd8ef449e43ff199ac08db5741537b961e8db9f1 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 4 Jun 2013 16:50:06 -0700 Subject: [PATCH 062/153] cleanup --- mediagoblin/auth/views.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 22120d10..b407c6ba 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -94,11 +94,6 @@ def login(request): if request.method == 'POST': username = login_form.username.data - if login_form.validate(): - user = check_login_simple(username, login_form.password.data) - - username = login_form.data['username'] - if login_form.validate(): user = check_login_simple(username, login_form.password.data) From 2d7b6bdef9f4aead59576b7bcbb2f42ba9c92ad7 Mon Sep 17 00:00:00 2001 From: Joar Wandborg Date: Sun, 7 Apr 2013 23:17:23 +0200 Subject: [PATCH 063/153] New notifications - Added request.notifications - Email configuration fixes - Set config_spec default SMTP port to `0` and switch to SSL/non-SSL default if `port == 0` - Added email_smtp_use_ssl configuration setting - Added migrations for notification tables - Added __repr__ to MediaComment(Mixin) - Added MediaComment.get_entry => MediaEntry - Added CommentSubscription, CommentNotification, Notification, ProcessingNotification tables - Added notifications.task to celery init - Fixed a bug in the video transcoder where pygst would hijack the --help argument. - Added notifications - views - silence - subscribe - routes - utility methods - celery task - Added half-hearted .active comment CSS style - Added quick JS to show header_dropdown - Added fragment template to show notifications in header_dropdown - Added fragment template to show subscribe/unsubscribe buttons on media/comment pages - Updated celery setup tests with notifications.task - Tried to fix test_misc tests that I broke - Added notification tests - Added and extended tests.tools fixtures - Integrated new notifications into media_home, media_post_comment views - Bumped SQLAlchemy dependency to >= 0.8.0 since we need polymorphic for the notifications to work --- mediagoblin/app.py | 3 + mediagoblin/config_spec.ini | 3 +- mediagoblin/db/migrations.py | 57 ++++++- mediagoblin/db/mixin.py | 9 ++ mediagoblin/db/models.py | 110 ++++++++++++- mediagoblin/init/celery/__init__.py | 18 ++- mediagoblin/media_types/stl/processing.py | 2 +- mediagoblin/media_types/video/transcoders.py | 6 + mediagoblin/notifications/__init__.py | 141 ++++++++++++++++ mediagoblin/notifications/routing.py | 25 +++ mediagoblin/notifications/task.py | 46 ++++++ mediagoblin/notifications/tools.py | 55 +++++++ mediagoblin/notifications/views.py | 54 +++++++ mediagoblin/routing.py | 1 + mediagoblin/static/css/base.css | 6 + mediagoblin/static/js/notifications.js | 18 +++ mediagoblin/submit/views.py | 4 + mediagoblin/templates/mediagoblin/base.html | 6 + .../fragments/header_notifications.html | 40 +++++ .../mediagoblin/user_pages/media.html | 2 + .../utils/comment-subscription.html | 36 +++++ mediagoblin/tests/test_celery_setup.py | 2 +- mediagoblin/tests/test_misc.py | 8 +- mediagoblin/tests/test_notifications.py | 151 ++++++++++++++++++ mediagoblin/tests/tools.py | 87 +++++++++- mediagoblin/tools/mail.py | 7 +- mediagoblin/user_pages/views.py | 21 ++- setup.py | 2 +- 28 files changed, 891 insertions(+), 29 deletions(-) create mode 100644 mediagoblin/notifications/__init__.py create mode 100644 mediagoblin/notifications/routing.py create mode 100644 mediagoblin/notifications/task.py create mode 100644 mediagoblin/notifications/tools.py create mode 100644 mediagoblin/notifications/views.py create mode 100644 mediagoblin/static/js/notifications.js create mode 100644 mediagoblin/templates/mediagoblin/fragments/header_notifications.html create mode 100644 mediagoblin/templates/mediagoblin/utils/comment-subscription.html create mode 100644 mediagoblin/tests/test_notifications.py diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 1984ce77..58058360 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -37,6 +37,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 import notifications _log = logging.getLogger(__name__) @@ -186,6 +187,8 @@ class MediaGoblinApp(object): request.urlgen = build_proxy + request.notifications = notifications + mg_request.setup_user_in_request(request) request.controller_name = None diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index b213970d..4547ea54 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -22,9 +22,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) diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 2c553396..29b2522a 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -26,7 +26,7 @@ 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.models import MediaEntry, Collection, User, MediaComment MIGRATIONS = {} @@ -287,3 +287,58 @@ def unique_collections_slug(db): constraint.create() 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(11, 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) diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index 9f566e36..1b32d838 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -31,6 +31,8 @@ import uuid import re import datetime +from datetime import datetime + from werkzeug.utils import cached_property from mediagoblin import mg_globals @@ -288,6 +290,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 2b925983..62090126 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -24,15 +24,17 @@ import datetime from sqlalchemy import Column, Integer, Unicode, UnicodeText, DateTime, \ Boolean, ForeignKey, UniqueConstraint, PrimaryKeyConstraint, \ SmallInteger -from sqlalchemy.orm import relationship, backref +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.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 @@ -60,9 +62,9 @@ class User(Base, UserMixin): # the RFC) and because it would be a mess to implement at this # point. email = Column(Unicode, nullable=False) - created = Column(DateTime, nullable=False, default=datetime.datetime.now) pw_hash = Column(Unicode, nullable=False) email_verified = Column(Boolean, default=False) + created = Column(DateTime, nullable=False, default=datetime.datetime.now) 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. @@ -392,6 +394,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. @@ -484,9 +490,103 @@ 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]) + 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, + CommentSubscription] ###################################################### 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/media_types/stl/processing.py b/mediagoblin/media_types/stl/processing.py index 49382495..ce7a5d37 100644 --- a/mediagoblin/media_types/stl/processing.py +++ b/mediagoblin/media_types/stl/processing.py @@ -46,7 +46,7 @@ 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 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/notifications/__init__.py b/mediagoblin/notifications/__init__.py new file mode 100644 index 00000000..4b7fbb8c --- /dev/null +++ b/mediagoblin/notifications/__init__.py @@ -0,0 +1,141 @@ +# 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 . + +import logging + +from mediagoblin.db.models import Notification, \ + CommentNotification, CommentSubscription +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) + + 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) + + 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) + + if only_unseen: + query = query.filter_by(seen=False) + + count = query.count() + + return count diff --git a/mediagoblin/notifications/routing.py b/mediagoblin/notifications/routing.py new file mode 100644 index 00000000..e57956d3 --- /dev/null +++ b/mediagoblin/notifications/routing.py @@ -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 . + +from mediagoblin.tools.routing import add_route + +add_route('mediagoblin.notifications.subscribe_comments', + '/u//m//notifications/subscribe/comments/', + 'mediagoblin.notifications.views:subscribe_comments') + +add_route('mediagoblin.notifications.silence_comments', + '/u//m//notifications/silence/', + 'mediagoblin.notifications.views:silence_comments') 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 . + +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 . + +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..d275bc92 --- /dev/null +++ b/mediagoblin/notifications/views.py @@ -0,0 +1,54 @@ +# 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 . + +from mediagoblin.tools.response import render_to_response, render_404, redirect +from mediagoblin.tools.translate import pass_to_ugettext as _ +from mediagoblin.decorators import (uses_pagination, get_user_media_entry, + get_media_entry_by_id, + require_active_login, user_may_delete_media, user_may_alter_collection, + get_user_collection, get_user_collection_item, active_user_from_url) + +from mediagoblin import messages + +from mediagoblin.notifications import add_comment_subscription, \ + silence_comment_subscription + +from werkzeug.exceptions import BadRequest + +@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)) diff --git a/mediagoblin/routing.py b/mediagoblin/routing.py index a650f22f..986eb2ed 100644 --- a/mediagoblin/routing.py +++ b/mediagoblin/routing.py @@ -35,6 +35,7 @@ def get_url_map(): import mediagoblin.edit.routing import mediagoblin.webfinger.routing import mediagoblin.listings.routing + import mediagoblin.notifications.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 5b8226e6..888d4e42 100644 --- a/mediagoblin/static/css/base.css +++ b/mediagoblin/static/css/base.css @@ -384,6 +384,12 @@ a.comment_whenlink:hover { margin-top: 8px; } +.comment_active { + box-shadow: 0px 0px 15px 15px #378566; + background: #378566; + color: #f7f7f7; +} + textarea#comment_content { resize: vertical; width: 100%; diff --git a/mediagoblin/static/js/notifications.js b/mediagoblin/static/js/notifications.js new file mode 100644 index 00000000..77793b34 --- /dev/null +++ b/mediagoblin/static/js/notifications.js @@ -0,0 +1,18 @@ +'use strict'; +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(); +}); diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py index a70c89b4..64e6791b 100644 --- a/mediagoblin/submit/views.py +++ b/mediagoblin/submit/views.py @@ -34,6 +34,8 @@ from mediagoblin.media_types import sniff_media, \ from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \ run_process_media, new_upload_entry +from mediagoblin.notifications import add_comment_subscription + @require_active_login def submit_start(request): @@ -92,6 +94,8 @@ def submit_start(request): run_process_media(entry, feed_url) add_message(request, SUCCESS, _('Woohoo! Submitted!')) + add_comment_subscription(request.user, entry) + return redirect(request, "mediagoblin.user_pages.user_home", user=request.user.username) except Exception as e: diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html index 6c7c07d0..f2723edb 100644 --- a/mediagoblin/templates/mediagoblin/base.html +++ b/mediagoblin/templates/mediagoblin/base.html @@ -34,6 +34,8 @@ src="{{ request.staticdirect('/js/extlib/jquery.js') }}"> + {# For clarification, the difference between the extra_head.html template # and the head template hook is that the former should be used by @@ -57,6 +59,9 @@
{%- if request.user %} {% if request.user and request.user.status == 'active' %} + + + {{ request.notifications.get_notification_count(request.user.id) }}
{% elif request.user and request.user.status == "needs_email_verification" %} @@ -109,6 +114,7 @@

{% endif %} + {% include 'mediagoblin/fragments/header_notifications.html' %}
{% endif %} diff --git a/mediagoblin/templates/mediagoblin/fragments/header_notifications.html b/mediagoblin/templates/mediagoblin/fragments/header_notifications.html new file mode 100644 index 00000000..613100aa --- /dev/null +++ b/mediagoblin/templates/mediagoblin/fragments/header_notifications.html @@ -0,0 +1,40 @@ +{% set notifications = request.notifications.get_notifications(request.user.id) %} +{% if notifications %} +
+

{% trans %}New comments{% endtrans %}

+ +
+{% endif %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index fb892fd7..a2a8f3b6 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -167,6 +167,8 @@ {% include "mediagoblin/utils/exif.html" %} + {% include "mediagoblin/utils/comment-subscription.html" %} + {%- if media.attachment_files|count %}

{% trans %}Attachments{% endtrans %}

- - {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/auth/forgot_password.html b/mediagoblin/templates/mediagoblin/auth/forgot_password.html index a6c9e1e9..6cfd2c85 100644 --- a/mediagoblin/templates/mediagoblin/auth/forgot_password.html +++ b/mediagoblin/templates/mediagoblin/auth/forgot_password.html @@ -29,12 +29,10 @@ {{ csrf_token }}

{% trans %}Recover password{% endtrans %}

- {{ wtforms_util.render_divs(fp_form) }} + {{ wtforms_util.render_divs(fp_form, True) }}
- - {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html index 2adbe547..d9f92557 100644 --- a/mediagoblin/templates/mediagoblin/auth/login.html +++ b/mediagoblin/templates/mediagoblin/auth/login.html @@ -45,7 +45,7 @@ {%- trans %}Create one here!{% endtrans %}

{% endif %} - {{ wtforms_util.render_divs(login_form) }} + {{ wtforms_util.render_divs(login_form, True) }} {% if pass_auth %}

@@ -61,6 +61,4 @@ {% endif %} - - {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html index 755d5418..b315975c 100644 --- a/mediagoblin/templates/mediagoblin/auth/register.html +++ b/mediagoblin/templates/mediagoblin/auth/register.html @@ -34,7 +34,7 @@ method="POST" enctype="multipart/form-data">

{% trans %}Create an account!{% endtrans %}

- {{ wtforms_util.render_divs(register_form) }} + {{ wtforms_util.render_divs(register_form, True) }} {{ csrf_token }}
- - {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html index be6976c2..90b237ee 100644 --- a/mediagoblin/templates/mediagoblin/utils/wtforms.html +++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html @@ -33,10 +33,14 @@ {%- endmacro %} {# Generically render a field #} -{% macro render_field_div(field) %} +{% macro render_field_div(field, autofocus_first=False) %} {{- render_label_p(field) }}
- {{ field }} + {% if autofocus_first %} + {{ field(autofocus=True) }} + {% else %} + {{ field }} + {% endif %} {%- if field.errors -%} {% for error in field.errors %}

{{ error }}

@@ -49,9 +53,13 @@ {%- 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 %} diff --git a/mediagoblin/tests/appconfig_context_modified.ini b/mediagoblin/tests/appconfig_context_modified.ini index 251c083c..80ca69b1 100644 --- a/mediagoblin/tests/appconfig_context_modified.ini +++ b/mediagoblin/tests/appconfig_context_modified.ini @@ -2,7 +2,6 @@ direct_remote_path = /test_static/ email_sender_address = "notice@mediagoblin.example.org" email_debug_mode = true -authentication_disabled = true # TODO: Switch to using an in-memory database sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db" diff --git a/mediagoblin/tests/appconfig_static_plugin.ini b/mediagoblin/tests/appconfig_static_plugin.ini index dbb789e0..dc251171 100644 --- a/mediagoblin/tests/appconfig_static_plugin.ini +++ b/mediagoblin/tests/appconfig_static_plugin.ini @@ -2,7 +2,6 @@ direct_remote_path = /test_static/ email_sender_address = "notice@mediagoblin.example.org" email_debug_mode = true -authentication_disabled = true # TODO: Switch to using an in-memory database sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db" diff --git a/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini b/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini index bbcb9163..a64e9e40 100644 --- a/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini +++ b/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini @@ -2,7 +2,6 @@ direct_remote_path = /test_static/ email_sender_address = "notice@mediagoblin.example.org" email_debug_mode = true -authentication_disabled = true # TODO: Switch to using an in-memory database sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db" diff --git a/mediagoblin/tests/auth_configs/no_auth_plugin_appconfig.ini b/mediagoblin/tests/auth_configs/no_auth_plugin_appconfig.ini deleted file mode 100644 index a64e9e40..00000000 --- a/mediagoblin/tests/auth_configs/no_auth_plugin_appconfig.ini +++ /dev/null @@ -1,25 +0,0 @@ -[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] diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index 83e71580..9f70c5ff 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -22,7 +22,6 @@ from mediagoblin import mg_globals from mediagoblin.db.models import User from mediagoblin.tests.tools import get_app, fixture_add_user from mediagoblin.tools import template, mail -from mediagoblin.auth.tools import AuthError from mediagoblin.auth import tools as auth_tools @@ -273,7 +272,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 # ------------------------- @@ -291,9 +289,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 # ----------------------- @@ -359,20 +355,6 @@ def test_authentication_views(test_app): assert urlparse.urlsplit(response.location)[2] == '/u/chris/' -# App with authentication_disabled and no auth plugin enabled -def no_auth_plugin_app(request): - return get_app( - request, - mgoblin_config=pkg_resources.resource_filename( - 'mediagoblin.tests.auth_configs', - 'no_auth_plugin_appconfig.ini')) - - -def test_auth_plugin_raises(request): - with pytest.raises(AuthError): - no_auth_plugin_app(request) - - @pytest.fixture() def authentication_disabled_app(request): return get_app( From f7698af1c118afa4f0db10cc0359d2b8b0e319b4 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 21 Jun 2013 17:24:33 -0500 Subject: [PATCH 079/153] Removing the "enter your password to change your email" bit. A good idea, though it feels fairly clumsy in the form, and I think if you're logged in you can already sabotage the user pretty well. This commit sponsored by Sergey Matveev. Thanks! --- mediagoblin/edit/forms.py | 6 --- mediagoblin/edit/views.py | 50 ++++++++----------- .../mediagoblin/edit/edit_account.html | 1 - mediagoblin/tests/test_edit.py | 38 -------------- 4 files changed, 21 insertions(+), 74 deletions(-) diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py index 3a502263..24b31a76 100644 --- a/mediagoblin/edit/forms.py +++ b/mediagoblin/edit/forms.py @@ -65,12 +65,6 @@ class EditAccountForm(wtforms.Form): _('New email address'), [wtforms.validators.Optional(), normalize_user_or_email_field(allow_user=False)]) - password = wtforms.PasswordField( - _('Password'), - [wtforms.validators.Optional(), - wtforms.validators.Length(min=5, max=1024)], - description=_( - 'Enter your old password to prove you own this account.')) license_preference = wtforms.SelectField( _('License preference'), [ diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index df7db21b..4eda61a2 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -236,38 +236,30 @@ def edit_account(request): user.license_preference = form.license_preference.data if form.new_email.data: - if not form.password.data: - form.password.errors.append( - _('This field is required.')) - elif not auth_lib.bcrypt_check_password( - form.password.data, user.pw_hash): - form.password.errors.append( - _('Wrong password.')) + 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.')) else: - 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.')) - else: - verification_key = get_timed_signer_url( - 'mail_verification_token').dumps({ - 'user': user.id, - 'email': new_email}) + 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)}) + 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) + email_debug_message(request) + auth_tools.send_verification_email(user, request, new_email, + rendered_email) if not form.errors: user.save() diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html index d56b3ba0..461dd6df 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_account.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html @@ -47,7 +47,6 @@

{{ wtforms_util.render_field_div(form.new_email) }} - {{ wtforms_util.render_field_div(form.password) }}

{{ form.wants_comment_notification }} {{ wtforms_util.render_label(form.wants_comment_notification) }}

diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py index 76fd5ee9..2afc519a 100644 --- a/mediagoblin/tests/test_edit.py +++ b/mediagoblin/tests/test_edit.py @@ -144,31 +144,6 @@ class TestUserEdit(object): def test_email_change(self, test_app): self.login(test_app) - # Test email change without password - template.clear_test_template_context() - test_app.post( - '/edit/account/', { - 'new_email': 'new@example.com'}) - - # Check form errors - context = template.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/edit/edit_account.html'] - assert context['form'].password.errors == [ - u'This field is required.'] - - # Test email change with wrong password - template.clear_test_template_context() - test_app.post( - '/edit/account/', { - 'new_email': 'new@example.com', - 'password': 'wrong'}) - - # Check form errors - context = template.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/edit/edit_account.html'] - assert context['form'].password.errors == [ - u'Wrong password.'] - # Test email already in db template.clear_test_template_context() test_app.post( @@ -182,19 +157,6 @@ class TestUserEdit(object): assert context['form'].new_email.errors == [ u'Sorry, a user with that email address already exists.'] - # Test password is too short - template.clear_test_template_context() - test_app.post( - '/edit/account/', { - 'new_email': 'new@example.com', - 'password': 't'}) - - # Check form errors - context = template.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/edit/edit_account.html'] - assert context['form'].password.errors == [ - u'Field must be between 5 and 1024 characters long.'] - # Test successful email change template.clear_test_template_context() res = test_app.post( From 75ee3de301e7bea30c40fe26d857bb6cc7878f82 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 22 Jun 2013 12:25:31 -0500 Subject: [PATCH 080/153] Fix by Rodney Ewing so render_http_exception works with newer Werkzeug versions. --- mediagoblin/tools/response.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py index aaf31d0b..0be1f835 100644 --- a/mediagoblin/tools/response.py +++ b/mediagoblin/tools/response.py @@ -77,7 +77,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) From 6331e927e47afb937bfde503864b164d49b05abd Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 22 Jun 2013 16:19:58 -0500 Subject: [PATCH 081/153] Padding on the header-dropdown area This helps make it a bit clearer that things are "contained inside" the header dropdown area. --- mediagoblin/static/css/base.css | 1 + 1 file changed, 1 insertion(+) diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css index 888d4e42..8b57584d 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 { From 56d1346789c2b628aa1af986c101010c426ecc56 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 22 Jun 2013 17:37:30 -0500 Subject: [PATCH 082/153] Fix the data integrity bug in test_misc. It turns out this has to do with some additions to the fixture adding of media entries. Since the new fake_upload field is True by default, adding multiple entries that have media_files at once meant that multiple additions of FileKeynames would be added at once if they were not saved at the same time. Tricky! Thankfully, Elrond helped us figure this one out. Thanks, Elrond :) And thanks also to Aapo Rantalainen for sponsoring this commit! --- mediagoblin/tests/test_misc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mediagoblin/tests/test_misc.py b/mediagoblin/tests/test_misc.py index 6af6bf92..43ad0b6d 100644 --- a/mediagoblin/tests/test_misc.py +++ b/mediagoblin/tests/test_misc.py @@ -29,9 +29,9 @@ def test_user_deletes_other_comments(test_app): user_b = fixture_add_user(u"chris_b") media_a = fixture_media_entry(uploader=user_a.id, save=False, - expunge=False) + expunge=False, fake_upload=False) media_b = fixture_media_entry(uploader=user_b.id, save=False, - expunge=False) + expunge=False, fake_upload=False) Session.add(media_a) Session.add(media_b) Session.flush() From c3de34d431c74fbdd44e08a5a4714a7a507b8e17 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 22 Jun 2013 17:40:12 -0500 Subject: [PATCH 083/153] Adding a docstring to fixture_media_entry It's not complete, but it makes clearer how to avoid errors with fake_upload :) This commit sponsored by Harper Sanford. Thank you! --- mediagoblin/tests/tools.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py index 836072b3..222649f1 100644 --- a/mediagoblin/tests/tools.py +++ b/mediagoblin/tests/tools.py @@ -234,6 +234,14 @@ def fixture_media_entry(title=u"Some title", slug=None, 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 From c1b342ba95e99407ccedfdfad306ddb36fde6eb0 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Mon, 24 Jun 2013 09:10:48 -0500 Subject: [PATCH 084/153] Reverting "No more of this find_packages nonsense." This reverts commit b75eb88fabdac4a9fdc863969ec9472110732607. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index a0a49a28..aaf5cda9 100644 --- a/setup.py +++ b/setup.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 . -from setuptools import setup +from setuptools import setup, find_packages import os import re @@ -36,7 +36,7 @@ def get_version(): setup( name="mediagoblin", version=get_version(), - packages=['mediagoblin'], + packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), zip_safe=False, include_package_data = True, # scripts and dependencies From 7fa4e19fc4e7d04175549ea2f21f8b741fbe69f2 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Tue, 25 Jun 2013 13:25:25 -0500 Subject: [PATCH 085/153] Add a bit more docs to plugin configuration This commit sponsored by Michael Rauch. Thank you! --- docs/source/pluginwriter/api.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/source/pluginwriter/api.rst b/docs/source/pluginwriter/api.rst index 66def173..29adb691 100644 --- a/docs/source/pluginwriter/api.rst +++ b/docs/source/pluginwriter/api.rst @@ -69,6 +69,32 @@ example might look like:: 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 ------------- From 5a1be074c0522c2151ab735eeb30a60c07ff7f7c Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 25 Jun 2013 13:22:56 -0700 Subject: [PATCH 086/153] typo --- mediagoblin/db/migrations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 50fccd78..129c1998 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -297,7 +297,7 @@ def pw_hash_nullable(db): user_table.c.pw_hash.alter(nullable=True) - if db.bind.url.drivername is 'sqlite': + if db.bind.url.drivername == 'sqlite': constraint = UniqueConstraint('username', table=user_table) constraint.create() From 6174169786beb98e6259c9d281f5571dd216a793 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 25 Jun 2013 13:43:33 -0700 Subject: [PATCH 087/153] cleanup after merge --- mediagoblin/auth/forms.py | 4 +++- mediagoblin/auth/tools.py | 13 +++++++------ mediagoblin/edit/views.py | 1 + 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index 866caa13..865502e9 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -29,7 +29,9 @@ class ForgotPassForm(wtforms.Form): class ChangePassForm(wtforms.Form): password = wtforms.PasswordField( - 'Password') + 'Password', + [wtforms.validators.Required(), + wtforms.validators.Length(min=5, max=1024)]) token = wtforms.HiddenField( '', [wtforms.validators.Required()]) diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index 877da14f..f3f92414 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -102,8 +102,8 @@ def send_verification_email(user, request, email=None, 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): @@ -114,14 +114,15 @@ 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', {'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.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/edit/views.py b/mediagoblin/edit/views.py index 429eb584..25a02446 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -24,6 +24,7 @@ from mediagoblin import messages from mediagoblin import mg_globals from mediagoblin import auth +from mediagoblin.auth import 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, From 15db1831514aeb9fd77b7bf43a2718b1ffc4d552 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Tue, 25 Jun 2013 17:12:33 -0500 Subject: [PATCH 088/153] Explain about sqlite dropping the constraint and why we're adding it back manually. --- mediagoblin/db/migrations.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index fef353af..98e8b139 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -371,6 +371,8 @@ def pw_hash_nullable(db): 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() From 1e21471a8abbf3f9d0d0e16a0f2c83c22ffe9650 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 25 Jun 2013 15:50:31 -0700 Subject: [PATCH 089/153] added feature to render_divs where if field.label == '' then it will render form.description the same a render_label --- mediagoblin/edit/forms.py | 5 +++-- mediagoblin/templates/mediagoblin/edit/edit_account.html | 7 +------ mediagoblin/templates/mediagoblin/utils/wtforms.html | 6 +++++- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py index 24b31a76..e0147a0c 100644 --- a/mediagoblin/edit/forms.py +++ b/mediagoblin/edit/forms.py @@ -65,6 +65,9 @@ class EditAccountForm(wtforms.Form): _('New email address'), [wtforms.validators.Optional(), normalize_user_or_email_field(allow_user=False)]) + wants_comment_notification = wtforms.BooleanField( + label='', + description=_("Email me when others comment on my media")) license_preference = wtforms.SelectField( _('License preference'), [ @@ -73,8 +76,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): diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html index 461dd6df..fa7a9c48 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_account.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html @@ -46,12 +46,7 @@ {% trans %}Change your password.{% endtrans %}

- {{ wtforms_util.render_field_div(form.new_email) }} -
-

{{ form.wants_comment_notification }} - {{ wtforms_util.render_label(form.wants_comment_notification) }}

-
- {{- wtforms_util.render_field_div(form.license_preference) }} + {{ wtforms_util.render_divs(form) }}
{{ csrf_token }} diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html index 90b237ee..f522172f 100644 --- a/mediagoblin/templates/mediagoblin/utils/wtforms.html +++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html @@ -47,7 +47,11 @@ {% endfor %} {%- endif %} {%- if field.description %} -

{{ field.description|safe }}

+ {% if field.label.text == '' %} + + {% else %} +

{{ field.description|safe }}

+ {% endif %} {%- endif %}
{%- endmacro %} From 4a698535bc97b37c8eb42ffea2cc3e7bd48565e6 Mon Sep 17 00:00:00 2001 From: Emily O'Leary Date: Tue, 25 Jun 2013 20:57:50 -0400 Subject: [PATCH 090/153] Improved test runtime from 352 seconds to 59 seconds by implementing an in-memory sqlite DB and including an option to run migrations on this newly created database by adding a config option called run_migrations to the config_spec and passing it along in app.py to the setup_database function. --- mediagoblin/app.py | 2 +- mediagoblin/config_spec.ini | 3 ++- mediagoblin/gmg_commands/dbupdate.py | 14 +++++++++++--- mediagoblin/init/__init__.py | 14 +++++++++----- mediagoblin/tests/appconfig_context_modified.ini | 5 +++-- mediagoblin/tests/appconfig_static_plugin.ini | 5 +++-- mediagoblin/tests/test_mgoblin_app.ini | 5 +++-- 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 58058360..3da166ab 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -86,7 +86,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) diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index 4547ea54..6b94901b 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -10,7 +10,8 @@ media_types = string_list(default=list("mediagoblin.media_types.image")) # database stuff sql_engine = string(default="sqlite:///%(here)s/mediagoblin.db") - +# Flag used during testing to determine if migrations should be run before the ORM is loaded +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") diff --git a/mediagoblin/gmg_commands/dbupdate.py b/mediagoblin/gmg_commands/dbupdate.py index fa25ecb2..1d9bbf1e 100644 --- a/mediagoblin/gmg_commands/dbupdate.py +++ b/mediagoblin/gmg_commands/dbupdate.py @@ -110,14 +110,22 @@ 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): + """ + Moved the migration part of run_dbupdate to a separate function so + it can be used to initialize the database during tests. + """ # 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/init/__init__.py b/mediagoblin/init/__init__.py index 444c624f..e0711416 100644 --- a/mediagoblin/init/__init__.py +++ b/mediagoblin/init/__init__.py @@ -58,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) diff --git a/mediagoblin/tests/appconfig_context_modified.ini b/mediagoblin/tests/appconfig_context_modified.ini index 80ca69b1..cc6721f5 100644 --- a/mediagoblin/tests/appconfig_context_modified.ini +++ b/mediagoblin/tests/appconfig_context_modified.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/user_dev/mediagoblin.db" +#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 diff --git a/mediagoblin/tests/appconfig_static_plugin.ini b/mediagoblin/tests/appconfig_static_plugin.ini index dc251171..5ce5c5bd 100644 --- a/mediagoblin/tests/appconfig_static_plugin.ini +++ b/mediagoblin/tests/appconfig_static_plugin.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/user_dev/mediagoblin.db" +#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 diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index 0466b53b..78905e33 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/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 From c345dcf8759cac4d38308a9a9f5826a61641f1ba Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 06:45:36 -0700 Subject: [PATCH 091/153] made edit_account to autofocus on the first field --- mediagoblin/templates/mediagoblin/edit/edit_account.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html index fa7a9c48..98b1b224 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_account.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html @@ -46,7 +46,7 @@ {% trans %}Change your password.{% endtrans %}

- {{ wtforms_util.render_divs(form) }} + {{ wtforms_util.render_divs(form, True) }}
{{ csrf_token }} From 889564a3c15eb15920be75ca53e0811a5c1c8fba Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 07:36:11 -0700 Subject: [PATCH 092/153] do the label thing only for boolean fields --- mediagoblin/templates/mediagoblin/utils/wtforms.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html index f522172f..635d4a41 100644 --- a/mediagoblin/templates/mediagoblin/utils/wtforms.html +++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html @@ -47,7 +47,7 @@ {% endfor %} {%- endif %} {%- if field.description %} - {% if field.label.text == '' %} + {% if and field.type == 'BooleanField' %} {% else %}

{{ field.description|safe }}

From 491f2007f5d1f5f595c37491b7f9c0c2b4c93963 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 07:39:17 -0700 Subject: [PATCH 093/153] typo --- mediagoblin/templates/mediagoblin/utils/wtforms.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html index 635d4a41..a4c33f1a 100644 --- a/mediagoblin/templates/mediagoblin/utils/wtforms.html +++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html @@ -47,7 +47,7 @@ {% endfor %} {%- endif %} {%- if field.description %} - {% if and field.type == 'BooleanField' %} + {% if field.type == 'BooleanField' %} {% else %}

{{ field.description|safe }}

From 6db23bd9b6cb9198a516065988d64c5322f9f175 Mon Sep 17 00:00:00 2001 From: Emily O'Leary Date: Thu, 27 Jun 2013 17:05:25 -0400 Subject: [PATCH 094/153] Updated comments for run_all_migrations and config_spec.ini. --- mediagoblin/config_spec.ini | 5 ++++- mediagoblin/gmg_commands/dbupdate.py | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index 6b94901b..12af2f57 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -10,8 +10,11 @@ media_types = string_list(default=list("mediagoblin.media_types.image")) # database stuff sql_engine = string(default="sqlite:///%(here)s/mediagoblin.db") -# Flag used during testing to determine if migrations should be run before the ORM is loaded + +# 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") diff --git a/mediagoblin/gmg_commands/dbupdate.py b/mediagoblin/gmg_commands/dbupdate.py index 1d9bbf1e..22ad426c 100644 --- a/mediagoblin/gmg_commands/dbupdate.py +++ b/mediagoblin/gmg_commands/dbupdate.py @@ -118,8 +118,12 @@ def run_dbupdate(app_config, global_config): def run_all_migrations(db, app_config, global_config): """ - Moved the migration part of run_dbupdate to a separate function so - it can be used to initialize the database during tests. + 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( From 4436fbcd01f4067dd335c0f2905f7fe841e3b301 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 28 Jun 2013 10:27:06 -0500 Subject: [PATCH 095/153] Some documentation on how to write database migrations. This commit sponsored by Andrei Cristian Petcu. Thanks! --- docs/source/devel/migrations.rst | 56 ++++++++++++++++++++++++++++++++ docs/source/index.rst | 1 + 2 files changed, 57 insertions(+) create mode 100644 docs/source/devel/migrations.rst diff --git a/docs/source/devel/migrations.rst b/docs/source/devel/migrations.rst new file mode 100644 index 00000000..bd9ac0da --- /dev/null +++ b/docs/source/devel/migrations.rst @@ -0,0 +1,56 @@ +.. 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 + . + +========== +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`. + +There's a few things you need to know: + +- We use `sqlalchemy-migrate + `_. + See `their docs `_. +- `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 d71f39f8..c8a3f040 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -87,6 +87,7 @@ This chapter contains various information for developers. devel/codebase devel/storage devel/originaldesigndecisions + devel/migrations Indices and tables From e9f3306627c106d6b3848deceb00cc321465b627 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 28 Jun 2013 11:51:40 -0500 Subject: [PATCH 096/153] More clarifications on what ./bin/gmg dbupdate does on each run. This commit sponsored by Jessica Howard. Thanks, sistah! --- docs/source/devel/migrations.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/source/devel/migrations.rst b/docs/source/devel/migrations.rst index bd9ac0da..16c02b04 100644 --- a/docs/source/devel/migrations.rst +++ b/docs/source/devel/migrations.rst @@ -20,6 +20,12 @@ 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 From 58a947578cde02244c08268205e6855bee408c94 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 1 Jul 2013 17:19:22 -0700 Subject: [PATCH 097/153] modified gmg to use plugin media_types and converted image media_type to new plugin style --- mediagoblin.ini | 5 --- mediagoblin/config_spec.ini | 3 -- mediagoblin/db/mixin.py | 15 +++---- mediagoblin/db/open.py | 4 -- mediagoblin/gmg_commands/dbupdate.py | 10 +---- mediagoblin/media_types/__init__.py | 49 +++++---------------- mediagoblin/media_types/image/__init__.py | 31 +++++++++++-- mediagoblin/media_types/image/processing.py | 7 ++- mediagoblin/user_pages/views.py | 2 +- 9 files changed, 52 insertions(+), 74 deletions(-) diff --git a/mediagoblin.ini b/mediagoblin.ini index e878a478..951e0d8a 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -19,11 +19,6 @@ email_debug_mode = true # Set to false to disable registrations allow_registration = true -## Uncomment this to turn on video or enable other media types -## You may have to install dependencies, and will have to run ./bin/gmg dbupdate -## See http://docs.mediagoblin.org/siteadmin/media-types.html for details. -# media_types = mediagoblin.media_types.image, mediagoblin.media_types.video - ## Uncomment this to put some user-overriding templates here # local_templates = %(here)s/user_dev/templates/ diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index 4547ea54..93643ee1 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -5,9 +5,6 @@ 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") diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index 1b32d838..2d878c80 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -29,15 +29,14 @@ real objects. import uuid import re -import datetime - from datetime import datetime from werkzeug.utils import cached_property from mediagoblin import mg_globals -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 @@ -204,14 +203,12 @@ 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('get_media_manager', self.media_type) + if manager: + return manager # 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_types in config?") def get_fail_exception(self): """ 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/gmg_commands/dbupdate.py b/mediagoblin/gmg_commands/dbupdate.py index fa25ecb2..4dfd7e92 100644 --- a/mediagoblin/gmg_commands/dbupdate.py +++ b/mediagoblin/gmg_commands/dbupdate.py @@ -42,7 +42,7 @@ class DatabaseData(object): self.name, self.models, 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. @@ -59,13 +59,6 @@ def gather_database_data(media_types, plugins): 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)) - for plugin in plugins: try: models = import_component('{0}.models:MODELS'.format(plugin)) @@ -112,7 +105,6 @@ def run_dbupdate(app_config, global_config): # Gather information from all media managers / projects dbdatas = gather_database_data( - app_config['media_types'], global_config.get('plugins', {}).keys()) # Set up the database diff --git a/mediagoblin/media_types/__init__.py b/mediagoblin/media_types/__init__.py index 20e1918e..2ce66f2a 100644 --- a/mediagoblin/media_types/__init__.py +++ b/mediagoblin/media_types/__init__.py @@ -15,12 +15,10 @@ # along with this program. If not, see . 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__) @@ -56,7 +54,7 @@ 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 @@ -98,40 +96,18 @@ def sniff_media(media): 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)) + media_type = hook_handle('sniff_handler', media_file, media=media) + if media_type: + _log.info('{0} accepts the file'.format(media_type)) + return media_type, hook_handle('get_media_managers', 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 +118,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/image/__init__.py b/mediagoblin/media_types/image/__init__.py index 5130ef48..b43dcb05 100644 --- a/mediagoblin/media_types/image/__init__.py +++ b/mediagoblin/media_types/image/__init__.py @@ -13,12 +13,20 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - import datetime from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.image.processing import process_image, \ sniff_handler +from mediagoblin.tools import pluginapi + + +ACCEPTED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "tiff"] +MEDIA_TYPE = 'mediagoblin.media_types.image' + + +def setup_plugin(): + config = pluginapi.get_config('mediagoblin.pluginapi.media_types.image') class ImageMediaManager(MediaManagerBase): @@ -27,9 +35,9 @@ class ImageMediaManager(MediaManagerBase): 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'] - + def get_original_date(self): """ Get the original date and time from the EXIF information. Returns @@ -52,4 +60,19 @@ class ImageMediaManager(MediaManagerBase): return None -MEDIA_MANAGER = ImageMediaManager +def get_media_manager(media_type): + if media_type == MEDIA_TYPE: + return ImageMediaManager + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return ImageMediaManager + + +hooks = { + 'setup': setup_plugin, + 'extensions': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + 'get_media_manager': get_media_manager, +} diff --git a/mediagoblin/media_types/image/processing.py b/mediagoblin/media_types/image/processing.py index bc0ce3f8..55f38ed5 100644 --- a/mediagoblin/media_types/image/processing.py +++ b/mediagoblin/media_types/image/processing.py @@ -35,6 +35,8 @@ 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): @@ -99,13 +101,14 @@ SUPPORTED_FILETYPES = ['png', 'gif', 'jpg', 'jpeg'] def sniff_handler(media_file, **kw): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) 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 + return MEDIA_TYPE else: _log.debug('Media present, extension not found in {0}'.format( SUPPORTED_FILETYPES)) @@ -113,7 +116,7 @@ def sniff_handler(media_file, **kw): _log.warning('Need additional information (keyword argument \'media\')' ' to be able to handle sniffing') - return False + return None def process_image(proc_state): diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index 83a524ec..596d4c20 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -142,7 +142,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, From 90b7b6e878772061e416fc462273b8cc2e8dea5d Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 1 Jul 2013 17:23:47 -0700 Subject: [PATCH 098/153] removed CompatMediaManager() since all core media_types are classes --- mediagoblin/media_types/__init__.py | 30 ----------------------------- 1 file changed, 30 deletions(-) diff --git a/mediagoblin/media_types/__init__.py b/mediagoblin/media_types/__init__.py index 2ce66f2a..395ba17a 100644 --- a/mediagoblin/media_types/__init__.py +++ b/mediagoblin/media_types/__init__.py @@ -50,36 +50,6 @@ 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): ''' Iterate through the enabled media types and find those suited From 2d9a452c3af11f54bb2bde628a06cec2f78b2309 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 2 Jul 2013 07:20:20 -0700 Subject: [PATCH 099/153] removed sniff_handler from Imange Media Manager class --- mediagoblin/media_types/image/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mediagoblin/media_types/image/__init__.py b/mediagoblin/media_types/image/__init__.py index b43dcb05..6303bbe0 100644 --- a/mediagoblin/media_types/image/__init__.py +++ b/mediagoblin/media_types/image/__init__.py @@ -32,7 +32,6 @@ def setup_plugin(): 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" From e699197258d5e1b5495e60cb2c238b3ff4f50ed4 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 2 Jul 2013 07:54:38 -0700 Subject: [PATCH 100/153] fixed some typos and enabled media_type plugins in tests --- mediagoblin.ini | 1 + mediagoblin/db/mixin.py | 3 ++- mediagoblin/media_types/image/__init__.py | 6 +++--- mediagoblin/tests/test_mgoblin_app.ini | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mediagoblin.ini b/mediagoblin.ini index 951e0d8a..035e7bcf 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -43,3 +43,4 @@ base_url = /mgoblin_media/ [plugins] [[mediagoblin.plugins.geolocation]] [[mediagoblin.plugins.basic_auth]] +[[mediagoblin.media_types.image]] diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index 2d878c80..26e41a3b 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -208,7 +208,8 @@ class MediaEntryMixin(GenerateSlugMixin): return manager # 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): """ diff --git a/mediagoblin/media_types/image/__init__.py b/mediagoblin/media_types/image/__init__.py index 6303bbe0..4b991588 100644 --- a/mediagoblin/media_types/image/__init__.py +++ b/mediagoblin/media_types/image/__init__.py @@ -26,7 +26,7 @@ MEDIA_TYPE = 'mediagoblin.media_types.image' def setup_plugin(): - config = pluginapi.get_config('mediagoblin.pluginapi.media_types.image') + config = pluginapi.get_config('mediagoblin.media_types.image') class ImageMediaManager(MediaManagerBase): @@ -66,12 +66,12 @@ def get_media_manager(media_type): def get_media_type_and_manager(ext): if ext in ACCEPTED_EXTENSIONS: - return ImageMediaManager + return MEDIA_TYPE, ImageMediaManager hooks = { 'setup': setup_plugin, - 'extensions': get_media_type_and_manager, + 'get_media_type_and_manager': get_media_type_and_manager, 'sniff_handler': sniff_handler, 'get_media_manager': get_media_manager, } diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index 5b060d36..ecd6c9d2 100644 --- a/mediagoblin/tests/test_mgoblin_app.ini +++ b/mediagoblin/tests/test_mgoblin_app.ini @@ -12,8 +12,6 @@ tags_max_length = 50 # So we can start to test attachments: allow_attachments = True -media_types = mediagoblin.media_types.image, mediagoblin.media_types.pdf - [storage:publicstore] base_dir = %(here)s/user_dev/media/public base_url = /mgoblin_media/ @@ -32,3 +30,5 @@ BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db" [[mediagoblin.plugins.httpapiauth]] [[mediagoblin.plugins.piwigo]] [[mediagoblin.plugins.basic_auth]] +[[mediagoblin.media_types.image]] +[[mediagoblin.media_types.pdf]] From 229308123196cbc7b3ba131da31eefb4c14d767e Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 2 Jul 2013 08:09:37 -0700 Subject: [PATCH 101/153] converted ascii media_type to plugin --- mediagoblin/media_types/ascii/__init__.py | 29 ++++++++++++++++++--- mediagoblin/media_types/ascii/processing.py | 6 +++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/mediagoblin/media_types/ascii/__init__.py b/mediagoblin/media_types/ascii/__init__.py index 0931e83a..bcba237c 100644 --- a/mediagoblin/media_types/ascii/__init__.py +++ b/mediagoblin/media_types/ascii/__init__.py @@ -17,15 +17,36 @@ from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.ascii.processing import process_ascii, \ sniff_handler +from mediagoblin.tools import pluginapi + +ACCEPTED_EXTENSIONS = ["txt", "asc", "nfo"] +MEDIA_TYPE = 'mediagoblin.media_types.ascii' + + +def setup_plugin(): + config = pluginapi.get_config(MEDIA_TYPE) class ASCIIMediaManager(MediaManagerBase): human_readable = "ASCII" processor = staticmethod(process_ascii) - sniff_handler = staticmethod(sniff_handler) display_template = "mediagoblin/media_displays/ascii.html" default_thumb = "images/media_thumbs/ascii.jpg" - accepted_extensions = ["txt", "asc", "nfo"] - -MEDIA_MANAGER = ASCIIMediaManager + +def get_media_manager(media_type): + if media_type == MEDIA_TYPE: + return ASCIIMediaManager + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, ASCIIMediaManager + + +hooks = { + 'setup': setup_plugin, + 'get_media_type_and_manager': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + 'get_media_manager': get_media_manager, +} diff --git a/mediagoblin/media_types/ascii/processing.py b/mediagoblin/media_types/ascii/processing.py index 2f6079be..aca784e8 100644 --- a/mediagoblin/media_types/ascii/processing.py +++ b/mediagoblin/media_types/ascii/processing.py @@ -28,17 +28,19 @@ 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): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) 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_EXTENSIONS: - return True + return MEDIA_TYPE - return False + return None def process_ascii(proc_state): From b1a763f61e8a848d2d5a8cfd68e2c45d31582b8f Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 2 Jul 2013 08:14:40 -0700 Subject: [PATCH 102/153] typo in image supported_filetypes --- mediagoblin/media_types/image/processing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/media_types/image/processing.py b/mediagoblin/media_types/image/processing.py index 55f38ed5..baf2ac7e 100644 --- a/mediagoblin/media_types/image/processing.py +++ b/mediagoblin/media_types/image/processing.py @@ -97,7 +97,7 @@ def resize_tool(proc_state, force, keyname, target_name, exif_tags, conversions_subdir) -SUPPORTED_FILETYPES = ['png', 'gif', 'jpg', 'jpeg'] +SUPPORTED_FILETYPES = ['png', 'gif', 'jpg', 'jpeg', 'tiff'] def sniff_handler(media_file, **kw): From df68438a34d3e913b78540216e1d9cc66ffbc401 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 2 Jul 2013 08:43:14 -0700 Subject: [PATCH 103/153] converted audio media_type to plugin --- mediagoblin/media_types/audio/__init__.py | 26 ++++++++++++++++++--- mediagoblin/media_types/audio/processing.py | 9 ++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/mediagoblin/media_types/audio/__init__.py b/mediagoblin/media_types/audio/__init__.py index 2eb7300e..dfe68660 100644 --- a/mediagoblin/media_types/audio/__init__.py +++ b/mediagoblin/media_types/audio/__init__.py @@ -17,14 +17,34 @@ from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.audio.processing import process_audio, \ sniff_handler +from mediagoblin.tools import pluginapi + +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" processor = staticmethod(process_audio) - sniff_handler = staticmethod(sniff_handler) display_template = "mediagoblin/media_displays/audio.html" - accepted_extensions = ["mp3", "flac", "wav", "m4a"] -MEDIA_MANAGER = AudioMediaManager +def get_media_manager(media_type): + if media_type == MEDIA_TYPE: + return AudioMediaManager + + +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, + 'get_media_manager': get_media_manager, +} diff --git a/mediagoblin/media_types/audio/processing.py b/mediagoblin/media_types/audio/processing.py index 101b83e5..22383bc1 100644 --- a/mediagoblin/media_types/audio/processing.py +++ b/mediagoblin/media_types/audio/processing.py @@ -27,19 +27,22 @@ from mediagoblin.media_types.audio.transcoders import (AudioTranscoder, _log = logging.getLogger(__name__) +MEDIA_TYPE = 'mediagoblin.media_types.audio' + def sniff_handler(media_file, **kw): + _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 + return None if data.is_audio == True and data.is_video == False: - return True + return MEDIA_TYPE - return False + return None def process_audio(proc_state): From 51e4e435046d043fd26da9ae5160a6ec3b7313f2 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 2 Jul 2013 08:48:47 -0700 Subject: [PATCH 104/153] converted pdf media_type to plugin --- mediagoblin/media_types/pdf/__init__.py | 26 ++++++++++++++++++++--- mediagoblin/media_types/pdf/processing.py | 9 +++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/mediagoblin/media_types/pdf/__init__.py b/mediagoblin/media_types/pdf/__init__.py index f0ba7867..c180507c 100644 --- a/mediagoblin/media_types/pdf/__init__.py +++ b/mediagoblin/media_types/pdf/__init__.py @@ -17,15 +17,35 @@ from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.pdf.processing import process_pdf, \ sniff_handler +from mediagoblin.tools import pluginapi + +ACCEPTED_EXTENSIONS = ['pdf'] +MEDIA_TYPE = 'mediagoblin.media_types.pdf' + + +def setup_plugin(): + config = pluginapi.get_config(MEDIA_TYPE) class PDFMediaManager(MediaManagerBase): human_readable = "PDF" processor = staticmethod(process_pdf) - sniff_handler = staticmethod(sniff_handler) display_template = "mediagoblin/media_displays/pdf.html" default_thumb = "images/media_thumbs/pdf.jpg" - accepted_extensions = ["pdf"] -MEDIA_MANAGER = PDFMediaManager +def get_media_manager(media_type): + if media_type == MEDIA_TYPE: + return PDFMediaManager + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, PDFMediaManager + +hooks = { + 'setup': setup_plugin, + 'get_media_type_and_manager': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + 'get_media_manager': get_media_manager, +} diff --git a/mediagoblin/media_types/pdf/processing.py b/mediagoblin/media_types/pdf/processing.py index 49742fd7..a1eeb307 100644 --- a/mediagoblin/media_types/pdf/processing.py +++ b/mediagoblin/media_types/pdf/processing.py @@ -25,6 +25,8 @@ 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 @@ -163,16 +165,17 @@ def check_prerequisites(): return True def sniff_handler(media_file, **kw): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) if not check_prerequisites(): - return False + return None 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_extensions(): - return True + return MEDIA_TYPE - return False + return None def create_pdf_thumb(original, thumb_filename, width, height): # Note: pdftocairo adds '.png', remove it From 239296b004483034373e645b3614d376a188f9b4 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 2 Jul 2013 08:52:33 -0700 Subject: [PATCH 105/153] converted stl media_type to plugin --- mediagoblin/media_types/stl/__init__.py | 26 ++++++++++++++++++++--- mediagoblin/media_types/stl/processing.py | 6 ++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/mediagoblin/media_types/stl/__init__.py b/mediagoblin/media_types/stl/__init__.py index 6ae8a8b9..192b5761 100644 --- a/mediagoblin/media_types/stl/__init__.py +++ b/mediagoblin/media_types/stl/__init__.py @@ -17,15 +17,35 @@ from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.stl.processing import process_stl, \ sniff_handler +from mediagoblin.tools import pluginapi + +MEDIA_TYPE = 'mediagoblin.media_types.stl' +ACCEPTED_EXTENSIONS = ["obj", "stl"] + + +def setup_plugin(): + config = pluginapi.get_config(MEDIA_TYPE) class STLMediaManager(MediaManagerBase): human_readable = "stereo lithographics" processor = staticmethod(process_stl) - sniff_handler = staticmethod(sniff_handler) display_template = "mediagoblin/media_displays/stl.html" default_thumb = "images/media_thumbs/video.jpg" - accepted_extensions = ["obj", "stl"] -MEDIA_MANAGER = STLMediaManager +def get_media_manager(media_type): + if media_type == MEDIA_TYPE: + return STLMediaManager + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, STLMediaManager + +hooks = { + 'setup': setup_plugin, + 'get_media_type_and_manager': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + 'get_media_manager': get_media_manager, +} diff --git a/mediagoblin/media_types/stl/processing.py b/mediagoblin/media_types/stl/processing.py index ce7a5d37..53751416 100644 --- a/mediagoblin/media_types/stl/processing.py +++ b/mediagoblin/media_types/stl/processing.py @@ -29,6 +29,7 @@ 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', @@ -43,13 +44,14 @@ BLEND_SCRIPT = pkg_resources.resource_filename( def sniff_handler(media_file, **kw): + _log.info('Sniffing {0}'.format(MEDIA_TYPE)) 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 + return MEDIA_TYPE else: _log.debug('Media present, extension not found in {0}'.format( SUPPORTED_FILETYPES)) @@ -57,7 +59,7 @@ def sniff_handler(media_file, **kw): _log.warning('Need additional information (keyword argument \'media\')' ' to be able to handle sniffing') - return False + return None def blender_render(config): From cbac4a7fc93fa44d669e36700c68019a19bd091d Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 2 Jul 2013 08:57:10 -0700 Subject: [PATCH 106/153] converted video media_type to plugin --- mediagoblin/media_types/video/__init__.py | 30 +++++++++++++++++---- mediagoblin/media_types/video/processing.py | 13 +++++---- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/mediagoblin/media_types/video/__init__.py b/mediagoblin/media_types/video/__init__.py index 569cf11a..aa4cdb93 100644 --- a/mediagoblin/media_types/video/__init__.py +++ b/mediagoblin/media_types/video/__init__.py @@ -17,20 +17,40 @@ from mediagoblin.media_types import MediaManagerBase from mediagoblin.media_types.video.processing import process_video, \ sniff_handler +from mediagoblin.tools import pluginapi + +MEDIA_TYPE = 'mediagoblin.media_types.video' +ACCEPTED_EXTENSIONS = [ + "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "m4v"] + + +def setup_plugin(): + config = pluginapi.get_config(MEDIA_TYPE) class VideoMediaManager(MediaManagerBase): human_readable = "Video" processor = staticmethod(process_video) - sniff_handler = staticmethod(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"] - + # 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_MANAGER = VideoMediaManager +def get_media_manager(media_type): + if media_type == MEDIA_TYPE: + return VideoMediaManager + + +def get_media_type_and_manager(ext): + if ext in ACCEPTED_EXTENSIONS: + return MEDIA_TYPE, VideoMediaManager + +hooks = { + 'setup': setup_plugin, + 'get_media_type_and_manager': get_media_type_and_manager, + 'sniff_handler': sniff_handler, + 'get_media_manager': get_media_manager, +} diff --git a/mediagoblin/media_types/video/processing.py b/mediagoblin/media_types/video/processing.py index ff2c94a0..5386ba60 100644 --- a/mediagoblin/media_types/video/processing.py +++ b/mediagoblin/media_types/video/processing.py @@ -29,6 +29,8 @@ from .util import skip_transcode _log = logging.getLogger(__name__) _log.setLevel(logging.DEBUG) +MEDIA_TYPE = 'mediagoblin.media_types.video' + class VideoTranscodingFail(BaseProcessingFail): ''' @@ -41,17 +43,18 @@ def sniff_handler(media_file, **kw): 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 + return None if data['is_video'] == True: - return True + return MEDIA_TYPE - return False + return None def process_video(proc_state): @@ -186,7 +189,7 @@ def store_metadata(media_entry, metadata): [(key, tags_metadata[key]) for key in [ "application-name", "artist", "audio-codec", "bitrate", - "container-format", "copyright", "encoder", + "container-format", "copyright", "encoder", "encoder-version", "license", "nominal-bitrate", "title", "video-codec"] if key in tags_metadata]) @@ -203,7 +206,7 @@ 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 From c81186dd2e300664d36583e9003736213d5aa7e9 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 2 Jul 2013 09:26:12 -0700 Subject: [PATCH 107/153] added a warning for old media types --- mediagoblin/app.py | 3 +++ mediagoblin/media_types/tools.py | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 mediagoblin/media_types/tools.py diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 96461711..11464a1f 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 @@ -69,6 +70,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() ########################################## 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 . +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.') From ac0bc6a1e1930e1fb898ce664e6ea8eb5efadbc7 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 3 Jul 2013 08:09:48 -0500 Subject: [PATCH 108/153] fixing the config section we pull things out of for basic_auth --- mediagoblin/plugins/basic_auth/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index a2efae92..0d3c6886 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -21,7 +21,7 @@ from sqlalchemy import or_ def setup_plugin(): - config = pluginapi.get_config('mediagoblin.pluginapi.basic_auth') + config = pluginapi.get_config('mediagoblin.plugins.basic_auth') def get_user(**kwargs): From 5adb906a0a4da32f22d4ebd868bfa92929c22011 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 11:20:50 -0700 Subject: [PATCH 109/153] merge --squash openid branch to take care of a false merge commit in the basic_auth branch that openid is forked from Commits squashed together (in reverse chronological order): - do the label thing only for boolean fields - made edit_account to autofocus on the first field - added feature to render_divs where if field.label == '' then it will render form.description the same a render_label - added allow_registration check - refactored create_user - removed verification_key from create_user - removed get_user from openid - cleanup after removing openid from template_env.globals - fix for werkzueg 0.9.1 - cleanup after merge - more tests - restored openid extra_validation just for safety - tests for openid - deleted openid extra_validation - passed next parameter in session for openid - fixed a bug that was deleting the messages - implemented openid store using sqlalchemy - ask openid provider for 'nickname' to prefill username in registration form - refactored delete openid url to work with generic urls such as google and to not allow a user to delete a url if it is there only one and they don't have a pw - refactored login to register user workflow, which fixed a problem where the 'or register with a password link' wasn't showing up when the finish_login view called the register view because there wasn't any redirect. - added the ability to remove openid's - added the ability to add openids to an existing account - refactored start_login and finish_login views - modified edit_account.html to use render_divs - modified gmg/edit/views to behave appropriatly if no password authentication is enabled. moved the update email stuff to it's own funtion to make edit_account view cleaner. edit_account now modifies the form depending on the plugins. - minor typos - added retrieving email from openid provider - moved allow_registration check to a decorator - moved check if auth is enabled to a decorator - changed openid user registration to go through login first - cleanup after merge - modified verification emails to use itsdangerous tokens - added error handling on bad token, fixed route, and added tests - added support for user to change email address - added link to login view openid/password in login template - updated openid get_user function - modified get_user function to take kwargs instead of username - no need for user might be email kwarg in check_login_simple - added gen_password_hash and check_password functions to auth/__init__ - added focus to form input - made imports fully qualified - modified basic_auth.check_login to check that the user has a pw_hash first - changed occurances of form.data['whatever'] to form.whatever.data - convert tabs to spaces in register template, remove unsed templates, and fixed trans tags in templates - in process of openid login. it works, but needs major imporvements - make password field required in basic_auth form - check if password field present in basic_auth create_user - modified openid create_user function - modified models based on Elronds suggestions - changed register form action to a variable to be passed in by the view using the template - openid plugin v0, still need to authenticate via openid. - added a register_user function to be able to use in a plugin's register view, and modified auth/views.register to redirect to openid/register if appropriate. - Modified basic_auth plugin to work with modified auth plugin hooks. Added context variables. Removed basic_auth/tools which was previously renamed to basic_auth/lib. - modified auth/__init__ hooks to work better with multiple plugins. Removed auth/lib.py. And added a basic_extra_verification function that all plugins will use. - added models and migrations for openid plugin --- mediagoblin/auth/tools.py | 9 + mediagoblin/auth/views.py | 22 +- mediagoblin/db/migrations.py | 2 +- mediagoblin/decorators.py | 35 +- mediagoblin/edit/views.py | 58 +-- mediagoblin/meddleware/csrf.py | 2 +- mediagoblin/plugins/basic_auth/__init__.py | 11 +- mediagoblin/plugins/openid/__init__.py | 122 ++++++ mediagoblin/plugins/openid/forms.py | 41 ++ mediagoblin/plugins/openid/lib.py | 28 ++ mediagoblin/plugins/openid/models.py | 65 +++ mediagoblin/plugins/openid/store.py | 128 ++++++ .../mediagoblin/plugins/openid/add.html | 44 ++ .../mediagoblin/plugins/openid/delete.html | 43 ++ .../mediagoblin/plugins/openid/login.html | 65 +++ .../plugins/openid/request_form.html | 24 ++ mediagoblin/plugins/openid/views.py | 405 ++++++++++++++++++ .../templates/mediagoblin/auth/login.html | 20 +- .../templates/mediagoblin/auth/register.html | 15 +- .../mediagoblin/edit/edit_account.html | 11 +- .../tests/auth_configs/openid_appconfig.ini | 41 ++ mediagoblin/tests/test_auth.py | 2 +- mediagoblin/tests/test_mgoblin_app.ini | 1 + mediagoblin/tests/test_openid.py | 372 ++++++++++++++++ 24 files changed, 1506 insertions(+), 60 deletions(-) create mode 100644 mediagoblin/plugins/openid/__init__.py create mode 100644 mediagoblin/plugins/openid/forms.py create mode 100644 mediagoblin/plugins/openid/lib.py create mode 100644 mediagoblin/plugins/openid/models.py create mode 100644 mediagoblin/plugins/openid/store.py create mode 100644 mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html create mode 100644 mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html create mode 100644 mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html create mode 100644 mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html create mode 100644 mediagoblin/plugins/openid/views.py create mode 100644 mediagoblin/tests/auth_configs/openid_appconfig.ini create mode 100644 mediagoblin/tests/test_openid.py diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py index f3f92414..579775ff 100644 --- a/mediagoblin/auth/tools.py +++ b/mediagoblin/auth/tools.py @@ -116,6 +116,7 @@ def send_fp_verification_email(user, 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', {'username': user.username, @@ -199,3 +200,11 @@ def no_auth_logout(request): 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 34500f91..1cff8dcc 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -14,12 +14,12 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import uuid from itsdangerous import BadSignature from mediagoblin import messages, mg_globals from mediagoblin.db.models import User 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.tools.mail import email_debug_message @@ -31,21 +31,14 @@ from mediagoblin.auth.tools import (send_verification_email, register_user, from mediagoblin import auth +@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 or no authentication - # is enabled - if not mg_globals.app_config["allow_registration"] or not mg_globals.app.auth: - 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') return redirect(request, 'mediagoblin.plugins.{0}.register'.format( @@ -71,20 +64,13 @@ def register(request): '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. """ - # Redirects to index page if no authentication is enabled - if not mg_globals.app.auth: - messages.add_message( - request, - messages.WARNING, - _('Sorry, authentication 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') return redirect(request, 'mediagoblin.plugins.{0}.login'.format( diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index 98e8b139..fe4ffb3e 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -307,6 +307,7 @@ def drop_token_related_User_columns(db): db.commit() + class CommentSubscription_v0(declarative_base()): __tablename__ = 'core__comment_subscriptions' id = Column(Integer, primary_key=True) @@ -378,4 +379,3 @@ def pw_hash_nullable(db): constraint.create() db.commit() - diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py index f3535fcf..ece222f5 100644 --- a/mediagoblin/decorators.py +++ b/mediagoblin/decorators.py @@ -18,11 +18,12 @@ from functools import wraps from urlparse import urljoin from werkzeug.exceptions import Forbidden, NotFound -from werkzeug.urls import url_quote from mediagoblin import mg_globals as mgg +from mediagoblin import messages from mediagoblin.db.models import MediaEntry, User from mediagoblin.tools.response import redirect, render_404 +from mediagoblin.tools.translate import pass_to_ugettext as _ def require_active_login(controller): @@ -235,3 +236,35 @@ 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 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 diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 25a02446..7a8d6185 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -236,30 +236,7 @@ def edit_account(request): user.license_preference = form.license_preference.data if form.new_email.data: - 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.')) - else: - 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) + _update_email(request, form, user) if not form.errors: user.save() @@ -365,6 +342,10 @@ def edit_collection(request, collection): @require_active_login def change_pass(request): + # If no password authentication, no need to change your password + if 'pass_auth' not in request.template_env.globals: + return redirect(request, 'index') + form = forms.ChangePassForm(request.form) user = request.user @@ -442,3 +423,32 @@ def verify_email(request): return redirect( request, 'mediagoblin.user_pages.user_home', user=user.username) + + +def _update_email(request, form, user): + 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.')) + + elif not users_with_email: + 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) 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/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 0d3c6886..2e7e8f8c 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -15,6 +15,7 @@ # along with this program. If not, see . 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_ @@ -38,9 +39,7 @@ def get_user(**kwargs): def create_user(registration_form): user = get_user(username=registration_form.username.data) if not user and 'password' in registration_form: - user = User() - user.username = registration_form.username.data - user.email = registration_form.email.data + user = create_basic_user(registration_form) user.pw_hash = gen_password_hash( registration_form.password.data) user.save() @@ -89,7 +88,7 @@ hooks = { 'auth_fake_login_attempt': auth_tools.fake_login_attempt, 'template_global_context': append_to_global_context, ('mediagoblin.plugins.openid.register', - 'mediagoblin/auth/register.html'): add_to_form_context, - ('mediagoblin.plugins.openid.login', - 'mediagoblin/auth/login.html'): add_to_form_context, + 'mediagoblin/auth/register.html'): add_to_form_context, + ('mediagoblin.plugins.openid.finish_login', + 'mediagoblin/auth/register.html'): add_to_form_context, } diff --git a/mediagoblin/plugins/openid/__init__.py b/mediagoblin/plugins/openid/__init__.py new file mode 100644 index 00000000..9803ada6 --- /dev/null +++ b/mediagoblin/plugins/openid/__init__.py @@ -0,0 +1,122 @@ +# 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 . +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')) + + +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, + ('mediagoblin.edit.account', + 'mediagoblin/edit/edit_account.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 . +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/lib.py b/mediagoblin/plugins/openid/lib.py new file mode 100644 index 00000000..bbe33d44 --- /dev/null +++ b/mediagoblin/plugins/openid/lib.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 . +import mediagoblin.plugins.openid.forms as auth_forms + + +def get_register_form(request): + # This function will check to see if persona plugin is enabled. If so, + # this function will call hook_transform? and return a modified form + # containing both openid & persona info. + return auth_forms.RegistrationForm(request.form) + + +def get_login_form(request): + # See register_form comment above + return auth_forms.LoginForm(request.form) 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 . +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..b54cf5c8 --- /dev/null +++ b/mediagoblin/plugins/openid/store.py @@ -0,0 +1,128 @@ +# 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 . +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 + + # Need to test these cleanups, not sure if the expired Association query + # will work + 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()) + expired = Association.query.filter( + 'issued + lifetime' < now) + count = expired.count() + for each in expired: + each.delete() + 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 . +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans %}Add an OpenID{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} +
+ {{ csrf_token }} +
+

{% trans %}Add an OpenID{% endtrans %}

+

+ + {% trans %}Delete an OpenID{% endtrans %} + +

+ {{ wtforms_util.render_divs(form, True) }} +
+ +
+
+
+{% 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 . +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block title -%} + {% trans %}Delete an OpenID{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} +
+ {{ csrf_token }} +
+

{% trans %}Delete an OpenID{% endtrans %}

+

+ + {% trans %}Add an OpenID{% endtrans %} + +

+ {{ wtforms_util.render_divs(form, True) }} +
+ +
+
+
+{% 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..33df7200 --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html @@ -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 . +#} +{% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + +{% block mediagoblin_head %} + +{% endblock %} + +{% block title -%} + {% trans %}Log in{% endtrans %} — {{ super() }} +{%- endblock %} + +{% block mediagoblin_content %} +
+ {{ csrf_token }} +
+

{% trans %}Log in{% endtrans %}

+ {% if login_failed %} +
+ {% trans %}Logging in failed!{% endtrans %} +
+ {% endif %} + {% if allow_registration %} +

+ {% trans %}Log in to create an account!{% endtrans %} +

+ {% endif %} + {% if pass_auth is defined %} +

+ + {%- trans %}Or login with a password!{% endtrans %} + +

+ {% endif %} + {{ wtforms_util.render_divs(login_form, True) }} +
+ +
+ {% if next %} + + {% 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..aa50eb1c --- /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 . +#} +{% extends "mediagoblin/base.html" %} + +{% block mediagoblin_content %} +
+ {{ html|safe }} + +{% endblock %} diff --git a/mediagoblin/plugins/openid/views.py b/mediagoblin/plugins/openid/views.py new file mode 100644 index 00000000..7ed6e6bd --- /dev/null +++ b/mediagoblin/plugins/openid/views.py @@ -0,0 +1,405 @@ +# 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 . +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 lib as auth_lib +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_lib.get_login_form(request) + 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.auth: + messages.add_message( + request, + messages.WARNING, + _('Sorry, authentication 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['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/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html index d9f92557..fa2e7201 100644 --- a/mediagoblin/templates/mediagoblin/auth/login.html +++ b/mediagoblin/templates/mediagoblin/auth/login.html @@ -29,7 +29,7 @@ {%- endblock %} {% block mediagoblin_content %} -
{{ csrf_token }}
@@ -41,16 +41,24 @@ {% endif %} {% if allow_registration %}

- {% trans %}Don't have an account yet?{% endtrans %} + {% trans %}Don't have an account yet?{% endtrans %} + {%- trans %}Create one here!{% endtrans %}

{% endif %} + {% if openid_link is defined %} +

+ + {%- trans %}Or login with OpenID!{% endtrans %} + +

+ {% endif %} {{ wtforms_util.render_divs(login_form, True) }} {% if pass_auth %} -

- - {% trans %}Forgot your password?{% endtrans %} -

+

+ + {% trans %}Forgot your password?{% endtrans %} +

{% endif %}
diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html index b315975c..9406f7ed 100644 --- a/mediagoblin/templates/mediagoblin/auth/register.html +++ b/mediagoblin/templates/mediagoblin/auth/register.html @@ -30,10 +30,23 @@ {% block mediagoblin_content %} -

{% trans %}Create an account!{% endtrans %}

+ {% if openid_link is defined %} +

+ + {%- trans %}Or register with OpenID!{% endtrans %} + +

+ {% elif pass_auth_link is defined %} +

+ + {%- trans %}Or register with a password!{% endtrans %} + +

+ {% endif %} {{ wtforms_util.render_divs(register_form, True) }} {{ csrf_token }}
diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html index 98b1b224..fe12a84a 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_account.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html @@ -41,13 +41,22 @@ Changing {{ username }}'s account settings {%- endtrans -%} + {% if pass_auth is defined %}

{% trans %}Change your password.{% endtrans %}

+ {% endif %} + {% if openid_link is defined %} +

+ + {% trans %}Edit your OpenID's{% endtrans %} + +

+ {% endif %} {{ wtforms_util.render_divs(form, True) }} -
+
{{ csrf_token }}
diff --git a/mediagoblin/tests/auth_configs/openid_appconfig.ini b/mediagoblin/tests/auth_configs/openid_appconfig.ini new file mode 100644 index 00000000..c2bd82fd --- /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 . +[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.openid]] diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index f973ebd8..5bd8bf2c 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -14,7 +14,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import urlparse -import datetime import pkg_resources import pytest @@ -236,6 +235,7 @@ def test_authentication_views(test_app): # Make a new user test_user = fixture_add_user(active_user=False) + # Get login # --------- test_app.get('/auth/login/') diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index 5b060d36..555dc4fa 100644 --- a/mediagoblin/tests/test_mgoblin_app.ini +++ b/mediagoblin/tests/test_mgoblin_app.ini @@ -32,3 +32,4 @@ BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db" [[mediagoblin.plugins.httpapiauth]] [[mediagoblin.plugins.piwigo]] [[mediagoblin.plugins.basic_auth]] +[[mediagoblin.plugins.openid]] diff --git a/mediagoblin/tests/test_openid.py b/mediagoblin/tests/test_openid.py new file mode 100644 index 00000000..c85f6318 --- /dev/null +++ b/mediagoblin/tests/test_openid.py @@ -0,0 +1,372 @@ +# 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 . +import urlparse +import pkg_resources +import pytest +import mock + +from openid.consumer.consumer import SuccessResponse + +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 = 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.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.find_one({ + 'username': u'chris'}) + 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='') + 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.find_one( + {'openid_url': u'http://add.myopenid.com'}) + 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.find_one( + {'openid_url': u'http://add.myopenid.com'}) + assert not new_openid + + _test_delete(self, test_user) From b01bff8b3c973887fd7063723ee1fb89d6f40a60 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 12:20:51 -0700 Subject: [PATCH 110/153] removed openid/lib, since the get forms functions were not needed for persona plugin --- mediagoblin/plugins/openid/lib.py | 28 ---------------------------- mediagoblin/plugins/openid/views.py | 3 +-- 2 files changed, 1 insertion(+), 30 deletions(-) delete mode 100644 mediagoblin/plugins/openid/lib.py diff --git a/mediagoblin/plugins/openid/lib.py b/mediagoblin/plugins/openid/lib.py deleted file mode 100644 index bbe33d44..00000000 --- a/mediagoblin/plugins/openid/lib.py +++ /dev/null @@ -1,28 +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 . -import mediagoblin.plugins.openid.forms as auth_forms - - -def get_register_form(request): - # This function will check to see if persona plugin is enabled. If so, - # this function will call hook_transform? and return a modified form - # containing both openid & persona info. - return auth_forms.RegistrationForm(request.form) - - -def get_login_form(request): - # See register_form comment above - return auth_forms.LoginForm(request.form) diff --git a/mediagoblin/plugins/openid/views.py b/mediagoblin/plugins/openid/views.py index 7ed6e6bd..b95144d0 100644 --- a/mediagoblin/plugins/openid/views.py +++ b/mediagoblin/plugins/openid/views.py @@ -23,7 +23,6 @@ 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 lib as auth_lib from mediagoblin.plugins.openid import forms as auth_forms from mediagoblin.plugins.openid.models import OpenIDUserURL from mediagoblin.plugins.openid.store import SQLAlchemyOpenIDStore @@ -139,7 +138,7 @@ def _response_nickname(response): @auth_enabled def login(request): """OpenID Login View""" - login_form = auth_lib.get_login_form(request) + login_form = auth_forms.LoginForm(request) allow_registration = mg_globals.app_config["allow_registration"] # Can't store next in request.GET because of redirects to OpenID provider From 664ce3bfaea6778c3fbca613ab66da881559f4c3 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 12:43:12 -0700 Subject: [PATCH 111/153] fixed openid store cleanupAssociations --- mediagoblin/plugins/openid/store.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mediagoblin/plugins/openid/store.py b/mediagoblin/plugins/openid/store.py index b54cf5c8..8f9a7012 100644 --- a/mediagoblin/plugins/openid/store.py +++ b/mediagoblin/plugins/openid/store.py @@ -105,8 +105,6 @@ class SQLAlchemyOpenIDStore(OpenIDStore): ononce.save() return True - # Need to test these cleanups, not sure if the expired Association query - # will work def cleanupNonces(self, _now=None): if _now is None: _now = int(time.time()) @@ -120,9 +118,10 @@ class SQLAlchemyOpenIDStore(OpenIDStore): def cleanupAssociations(self): now = int(time.time()) - expired = Association.query.filter( - 'issued + lifetime' < now) - count = expired.count() - for each in expired: - each.delete() + assoc = Association.query.all() + count = 0 + for each in assoc: + if (each.lifetime + each.issued) <= now: + each.delete() + count = count + 1 return count From ef146456b1a2648b9f137593f0a551d16a69965a Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 12:44:37 -0700 Subject: [PATCH 112/153] typo --- .../templates/mediagoblin/plugins/openid/request_form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html index aa50eb1c..68d028d0 100644 --- a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html @@ -20,5 +20,5 @@ {% block mediagoblin_content %}
{{ html|safe }} - +
{% endblock %} From d66f79031e07447ab22cb19a610f388ff85ce249 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 12:53:02 -0700 Subject: [PATCH 113/153] forgot to pass request.form into LoginForm class --- mediagoblin/plugins/openid/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/plugins/openid/views.py b/mediagoblin/plugins/openid/views.py index b95144d0..9566e38e 100644 --- a/mediagoblin/plugins/openid/views.py +++ b/mediagoblin/plugins/openid/views.py @@ -138,7 +138,7 @@ def _response_nickname(response): @auth_enabled def login(request): """OpenID Login View""" - login_form = auth_forms.LoginForm(request) + 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 From fea0b3b289154c96017021d25b0ed455d6f7f7b4 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 3 Jul 2013 07:16:31 -0700 Subject: [PATCH 114/153] use template hooks instead of hardcoding in templates --- mediagoblin/plugins/basic_auth/__init__.py | 9 ------- mediagoblin/plugins/openid/__init__.py | 9 ++++--- .../mediagoblin/plugins/openid/edit_link.html | 25 +++++++++++++++++ .../plugins/openid/login_link.html | 25 +++++++++++++++++ .../plugins/openid/register_link.html | 27 +++++++++++++++++++ .../templates/mediagoblin/auth/login.html | 8 +----- .../templates/mediagoblin/auth/register.html | 14 +--------- .../mediagoblin/edit/edit_account.html | 8 +----- 8 files changed, 85 insertions(+), 40 deletions(-) create mode 100644 mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html create mode 100644 mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html create mode 100644 mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index 2e7e8f8c..c16d8855 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -71,11 +71,6 @@ def append_to_global_context(context): return context -def add_to_form_context(context): - context['pass_auth_link'] = True - return context - - hooks = { 'setup': setup_plugin, 'authentication': auth, @@ -87,8 +82,4 @@ hooks = { 'auth_check_password': check_password, 'auth_fake_login_attempt': auth_tools.fake_login_attempt, 'template_global_context': append_to_global_context, - ('mediagoblin.plugins.openid.register', - 'mediagoblin/auth/register.html'): add_to_form_context, - ('mediagoblin.plugins.openid.finish_login', - 'mediagoblin/auth/register.html'): add_to_form_context, } diff --git a/mediagoblin/plugins/openid/__init__.py b/mediagoblin/plugins/openid/__init__.py index 9803ada6..1ee60fbf 100644 --- a/mediagoblin/plugins/openid/__init__.py +++ b/mediagoblin/plugins/openid/__init__.py @@ -56,6 +56,11 @@ def setup_plugin(): pluginapi.register_routes(routes) pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates')) + pluginapi.register_template_hooks( + {'openid_register_link': 'mediagoblin/plugins/openid/register_link.html', + 'openid_login_link': 'mediagoblin/plugins/openid/login_link.html', + 'openid_edit_link': 'mediagoblin/plugins/openid/edit_link.html'}) + def create_user(register_form): if 'openid' in register_form: @@ -115,8 +120,4 @@ hooks = { '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, - ('mediagoblin.edit.account', - 'mediagoblin/edit/edit_account.html'): add_to_form_context, } 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..2e63e1f8 --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/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 . +#} + +{% block openid_edit_link %} +

+ + {% trans %}Edit your OpenID's{% endtrans %} + +

+{% 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..e5e77d01 --- /dev/null +++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/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 . +#} + +{% block openid_login_link %} +

+ + {%- trans %}Or login with OpenID!{% endtrans %} + +

+{% 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 . +#} + +{% block openid_register_link %} + {% if openid_link is defined %} +

+ + {%- trans %}Or register with OpenID!{% endtrans %} + +

+ {% endif %} +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html index fa2e7201..2f821c0e 100644 --- a/mediagoblin/templates/mediagoblin/auth/login.html +++ b/mediagoblin/templates/mediagoblin/auth/login.html @@ -46,13 +46,7 @@ {%- trans %}Create one here!{% endtrans %}

{% endif %} - {% if openid_link is defined %} -

- - {%- trans %}Or login with OpenID!{% endtrans %} - -

- {% endif %} + {% template_hook("openid_login_link") %} {{ wtforms_util.render_divs(login_form, True) }} {% if pass_auth %}

diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html index 9406f7ed..1e4b1858 100644 --- a/mediagoblin/templates/mediagoblin/auth/register.html +++ b/mediagoblin/templates/mediagoblin/auth/register.html @@ -34,19 +34,7 @@ method="POST" enctype="multipart/form-data">

{% trans %}Create an account!{% endtrans %}

- {% if openid_link is defined %} -

- - {%- trans %}Or register with OpenID!{% endtrans %} - -

- {% elif pass_auth_link is defined %} -

- - {%- trans %}Or register with a password!{% endtrans %} - -

- {% endif %} + {% template_hook("openid_register_link") %} {{ wtforms_util.render_divs(register_form, True) }} {{ csrf_token }}
diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html index fe12a84a..86c54d79 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_account.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html @@ -48,13 +48,7 @@

{% endif %} - {% if openid_link is defined %} -

- - {% trans %}Edit your OpenID's{% endtrans %} - -

- {% endif %} + {% template_hook("openid_edit_link") %} {{ wtforms_util.render_divs(form, True) }}
From c92b3c63b13ad44e8485a577f5fb768c9bdc1f94 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 3 Jul 2013 08:09:06 -0700 Subject: [PATCH 115/153] changed hook name to reuse with persona --- mediagoblin/plugins/openid/__init__.py | 6 +++--- mediagoblin/templates/mediagoblin/auth/login.html | 2 +- mediagoblin/templates/mediagoblin/auth/register.html | 2 +- mediagoblin/templates/mediagoblin/edit/edit_account.html | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mediagoblin/plugins/openid/__init__.py b/mediagoblin/plugins/openid/__init__.py index 1ee60fbf..ee88808c 100644 --- a/mediagoblin/plugins/openid/__init__.py +++ b/mediagoblin/plugins/openid/__init__.py @@ -57,9 +57,9 @@ def setup_plugin(): pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates')) pluginapi.register_template_hooks( - {'openid_register_link': 'mediagoblin/plugins/openid/register_link.html', - 'openid_login_link': 'mediagoblin/plugins/openid/login_link.html', - 'openid_edit_link': 'mediagoblin/plugins/openid/edit_link.html'}) + {'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): diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html index 2f821c0e..3329b5d0 100644 --- a/mediagoblin/templates/mediagoblin/auth/login.html +++ b/mediagoblin/templates/mediagoblin/auth/login.html @@ -46,7 +46,7 @@ {%- trans %}Create one here!{% endtrans %}

{% endif %} - {% template_hook("openid_login_link") %} + {% template_hook("login_link") %} {{ wtforms_util.render_divs(login_form, True) }} {% if pass_auth %}

diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html index 1e4b1858..a7b8033f 100644 --- a/mediagoblin/templates/mediagoblin/auth/register.html +++ b/mediagoblin/templates/mediagoblin/auth/register.html @@ -34,7 +34,7 @@ method="POST" enctype="multipart/form-data">

{% trans %}Create an account!{% endtrans %}

- {% template_hook("openid_register_link") %} + {% template_hook("register_link") %} {{ wtforms_util.render_divs(register_form, True) }} {{ csrf_token }}
diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html index 86c54d79..a10949f5 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_account.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html @@ -48,7 +48,7 @@

{% endif %} - {% template_hook("openid_edit_link") %} + {% template_hook(edit_link") %} {{ wtforms_util.render_divs(form, True) }}
From 87bca496b28ec9b98144747767bb1c8e8dec4676 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 3 Jul 2013 14:06:22 -0500 Subject: [PATCH 116/153] Fix missing quote --- mediagoblin/templates/mediagoblin/edit/edit_account.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html index a10949f5..51293acb 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_account.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html @@ -48,7 +48,7 @@

{% endif %} - {% template_hook(edit_link") %} + {% template_hook("edit_link") %} {{ wtforms_util.render_divs(form, True) }}
From 5622cc44edfb2d653ae67946fa9ea130c5f7fcaa Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Tue, 9 Jul 2013 19:40:04 -0500 Subject: [PATCH 117/153] Mention setup.py develop --upgrade also in release notes. This commit sponsored by Christoph Schumacher. Thank you! --- docs/source/siteadmin/relnotes.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/source/siteadmin/relnotes.rst b/docs/source/siteadmin/relnotes.rst index 7b6d8353..7ae305a7 100644 --- a/docs/source/siteadmin/relnotes.rst +++ b/docs/source/siteadmin/relnotes.rst @@ -25,7 +25,9 @@ carefully, or at least skim over it. ===== **Do this to upgrade** -1. Make sure to run ``bin/gmg dbupdate`` after upgrading. +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. From 2d7a6789be0334935a362676fcb13182ac5b9780 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 10 Jul 2013 08:45:18 -0500 Subject: [PATCH 118/153] Fixing bug that effectively broke document support in 0.4.0.. how embarassing :( This fix sponsored by Christophe Drevet. Thank you! --- mediagoblin/media_types/pdf/processing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mediagoblin/media_types/pdf/processing.py b/mediagoblin/media_types/pdf/processing.py index 49742fd7..b5adb5e6 100644 --- a/mediagoblin/media_types/pdf/processing.py +++ b/mediagoblin/media_types/pdf/processing.py @@ -250,8 +250,8 @@ def process_pdf(proc_state): else: pdf_filename = queued_filename.rsplit('.', 1)[0] + '.pdf' unoconv = where('unoconv') - call(executable=unoconv, - args=[unoconv, '-v', '-f', 'pdf', queued_filename]) + Popen(executable=unoconv, + args=[unoconv, '-v', '-f', 'pdf', queued_filename]).wait() if not os.path.exists(pdf_filename): _log.debug('unoconv failed to convert file to pdf') raise BadMediaFail() From bed9ad06b79eae9072d3172ddcf4cc5e778441a9 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 10 Jul 2013 11:41:29 -0500 Subject: [PATCH 119/153] Release notes v0.4.1 ... fixes serious issue with conversion via libreoffice. This commit sponsored by William Linna. Thank you! --- docs/source/siteadmin/relnotes.rst | 11 +++++++++++ mediagoblin/_version.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/source/siteadmin/relnotes.rst b/docs/source/siteadmin/relnotes.rst index 7b6d8353..e8c9477e 100644 --- a/docs/source/siteadmin/relnotes.rst +++ b/docs/source/siteadmin/relnotes.rst @@ -21,6 +21,17 @@ 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.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. + + 0.4.0 ===== diff --git a/mediagoblin/_version.py b/mediagoblin/_version.py index cb230a60..1aa0e2c4 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" +__version__ = "0.4.1" From b3c4cbd5c16d07937fb9486a88deec29f8aaeb0d Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 8 Jul 2013 16:27:43 -0700 Subject: [PATCH 120/153] only check password if there is a store_hash --- mediagoblin/plugins/basic_auth/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py index c16d8855..33a554b0 100644 --- a/mediagoblin/plugins/basic_auth/__init__.py +++ b/mediagoblin/plugins/basic_auth/__init__.py @@ -59,7 +59,10 @@ def gen_password_hash(raw_pass, extra_salt=None): def check_password(raw_pass, stored_hash, extra_salt=None): - return auth_tools.bcrypt_check_password(raw_pass, stored_hash, extra_salt) + if stored_hash: + return auth_tools.bcrypt_check_password(raw_pass, + stored_hash, extra_salt) + return None def auth(): From 05ceada051dad011bb9b3e1c93fb42b2d9875939 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 10 Jul 2013 10:37:13 -0700 Subject: [PATCH 121/153] remove the list from response.vary. not sure why I was getting an error using openid without it, but everything seems to be working fine now --- mediagoblin/meddleware/csrf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/meddleware/csrf.py b/mediagoblin/meddleware/csrf.py index 44d42d75..661f0ba2 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 = list(getattr(response, 'vary', None) or []) + ['Cookie'] + response.vary = (getattr(response, 'vary', None) or []) + ['Cookie'] def _make_token(self, request): """Generate a new token to use for CSRF protection.""" From 537ce5973aef0c392be620d24993831812515df5 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 10 Jul 2013 11:08:28 -0700 Subject: [PATCH 122/153] need to use .get('messages') to not get a keyerror --- mediagoblin/plugins/openid/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/plugins/openid/views.py b/mediagoblin/plugins/openid/views.py index 9566e38e..b639a4cb 100644 --- a/mediagoblin/plugins/openid/views.py +++ b/mediagoblin/plugins/openid/views.py @@ -342,7 +342,7 @@ def delete_openid(request): form.openid.errors.append( _('That OpenID is not registered to this account.')) - if not form.errors and not request.session['messages']: + 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') From cd1fda4d947bf13ed3708859f83cef6160538751 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 10 Jul 2013 13:34:49 -0500 Subject: [PATCH 123/153] PyTest needs to be >= 2.3.1 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f320e92c..f28a2bb0 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ setup( 'PasteScript', 'wtforms', 'py-bcrypt', - 'pytest>=2.3', + 'pytest>=2.3.1', 'pytest-xdist', 'werkzeug>=0.7', 'celery==2.5.3', From 20e4e6c140f852e5142f930dd15684497fb9468a Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sat, 22 Jun 2013 12:25:31 -0500 Subject: [PATCH 124/153] Fix by Rodney Ewing so render_http_exception works with newer Werkzeug versions. This commit back-cherry-picked from current master for the 0.4.1 fix release. --- mediagoblin/tools/response.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py index aaf31d0b..0be1f835 100644 --- a/mediagoblin/tools/response.py +++ b/mediagoblin/tools/response.py @@ -77,7 +77,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) From d3b1fd2e606f549c5ecc2a31c94d90aa93794005 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 10 Jul 2013 16:29:50 -0500 Subject: [PATCH 125/153] Updating docs regarding pulling in and fetching git submodules We use this for PDF.js now... we should reference that. This commit sponsored by Bonnie King. Thanks! --- docs/source/siteadmin/deploying.rst | 5 +++-- docs/source/siteadmin/relnotes.rst | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/source/siteadmin/deploying.rst b/docs/source/siteadmin/deploying.rst index 0ee6b5b4..9d7f83c1 100644 --- a/docs/source/siteadmin/deploying.rst +++ b/docs/source/siteadmin/deploying.rst @@ -157,9 +157,10 @@ directory. Modify these commands to reflect your own environment:: mkdir -p /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 + git submodule init && git submodule fetch And set up the in-package virtualenv:: @@ -194,7 +195,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 diff --git a/docs/source/siteadmin/relnotes.rst b/docs/source/siteadmin/relnotes.rst index e8c9477e..2666b0a8 100644 --- a/docs/source/siteadmin/relnotes.rst +++ b/docs/source/siteadmin/relnotes.rst @@ -31,6 +31,8 @@ fix in the newly released document support which prevented the 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 ===== @@ -56,6 +58,9 @@ switch and restarting mediagoblin/celery with no other actions. 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 fetch`` + You will need to do this to use the new PDF support. **For theme authors** From a66fbf97d277222106002805723723b4b5bef726 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 10 Jul 2013 17:41:16 -0500 Subject: [PATCH 126/153] A few small formatting fixes on the release notes --- docs/source/siteadmin/relnotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/siteadmin/relnotes.rst b/docs/source/siteadmin/relnotes.rst index b49d1654..8e7ba396 100644 --- a/docs/source/siteadmin/relnotes.rst +++ b/docs/source/siteadmin/relnotes.rst @@ -21,6 +21,7 @@ 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.4.1 ===== @@ -38,6 +39,7 @@ Otherwise, follow 0.4.0 instructions. ===== **Do this to upgrade** + 1. Make sure to run ``./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate`` after upgrading. From 53d78991d7122c93c92cddee81a9e3768c6420e9 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Wed, 10 Jul 2013 17:58:30 -0500 Subject: [PATCH 127/153] Revert "remove the list from response.vary. not sure why I was getting an error using openid without it, but everything seems to be working fine now" This reverts commit 05ceada051dad011bb9b3e1c93fb42b2d9875939. It turns out the reason for this in the first place was werkzeug backwards compatibility. --- mediagoblin/meddleware/csrf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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.""" From 9609ddc0a6a071a2876cb1e2eff695f12f8fe39c Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 11 Jul 2013 12:34:43 -0700 Subject: [PATCH 128/153] should use media.slug_or_id incase a MediaEntry doesn't have a slug --- .../templates/mediagoblin/utils/comment-subscription.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mediagoblin/templates/mediagoblin/utils/comment-subscription.html b/mediagoblin/templates/mediagoblin/utils/comment-subscription.html index 8ee8c883..bd367e80 100644 --- a/mediagoblin/templates/mediagoblin/utils/comment-subscription.html +++ b/mediagoblin/templates/mediagoblin/utils/comment-subscription.html @@ -21,13 +21,13 @@ {% if not subscription or not subscription.notify %} Subscribe to comments {% else %} Silence comments {% endif %} From 3aeca53c85981fa46d61b41a7cf648d90637eb62 Mon Sep 17 00:00:00 2001 From: dunkyp Date: Tue, 6 Nov 2012 17:47:48 +0000 Subject: [PATCH 129/153] fixes the inability to upload non ascii filenames, werkzeug strips all non ascii chars and returns an empty string. This checks if the filename contains non asciis and if it does generates a uuid for filename. Also the request version of filename is used for generating alternative title for upload cherry-picked from dunkyp. fixed conflicts and missing import. --- mediagoblin/submit/views.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py index 64e6791b..0fe280f1 100644 --- a/mediagoblin/submit/views.py +++ b/mediagoblin/submit/views.py @@ -19,6 +19,7 @@ import mediagoblin.mg_globals as mg_globals from os.path import splitext import logging +import uuid _log = logging.getLogger(__name__) @@ -53,6 +54,10 @@ def submit_start(request): try: filename = request.files['file'].filename + # 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( @@ -63,7 +68,7 @@ def submit_start(request): entry.media_type = unicode(media_type) entry.title = ( unicode(submit_form.title.data) - or unicode(splitext(filename)[0])) + or unicode(splitext(request.files['file'].filename)[0])) entry.description = unicode(submit_form.description.data) From 44082b12d8a418bacd1ca5b19f7ce2595e07c1ee Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 11 Jul 2013 14:17:50 -0700 Subject: [PATCH 130/153] Patch by Strum. Ticket #451 - Convert all mongokit style .find, .find_one, .one calls over to SQLAlchemy queries --- mediagoblin/db/base.py | 12 ------------ mediagoblin/db/util.py | 2 +- mediagoblin/decorators.py | 22 +++++++++++----------- mediagoblin/edit/views.py | 6 +++--- mediagoblin/gmg_commands/import_export.py | 4 ++-- mediagoblin/gmg_commands/users.py | 12 +++++++----- mediagoblin/submit/views.py | 6 +++--- mediagoblin/tests/test_auth.py | 12 ++++++------ mediagoblin/tests/test_edit.py | 4 ++-- mediagoblin/tests/test_openid.py | 12 ++++++------ mediagoblin/tests/test_submission.py | 10 +++++----- mediagoblin/tests/tools.py | 2 +- 12 files changed, 47 insertions(+), 57 deletions(-) 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/util.py b/mediagoblin/db/util.py index 6ffec44d..8431361a 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() diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py index ece222f5..ca7be53c 100644 --- a/mediagoblin/decorators.py +++ b/mediagoblin/decorators.py @@ -87,8 +87,8 @@ 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 + creator_id = request.db.User.query.filter_by( + username=request.matchdict['user']).first().id if not (request.user.is_admin or request.user.id == creator_id): raise Forbidden() @@ -162,15 +162,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: @@ -187,14 +187,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: diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index 7a8d6185..6aa2acd9 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -305,9 +305,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( diff --git a/mediagoblin/gmg_commands/import_export.py b/mediagoblin/gmg_commands/import_export.py index d51a1e3e..98ec617d 100644 --- a/mediagoblin/gmg_commands/import_export.py +++ b/mediagoblin/gmg_commands/import_export.py @@ -63,7 +63,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 +204,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, diff --git a/mediagoblin/gmg_commands/users.py b/mediagoblin/gmg_commands/users.py index 1f329459..e44b0aa9 100644 --- a/mediagoblin/gmg_commands/users.py +++ b/mediagoblin/gmg_commands/users.py @@ -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.' @@ -71,7 +71,8 @@ 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.save() @@ -94,7 +95,8 @@ 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.gen_password_hash(args.password) user.save() diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py index 0fe280f1..3f9d5b2d 100644 --- a/mediagoblin/submit/views.py +++ b/mediagoblin/submit/views.py @@ -138,9 +138,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/tests/test_auth.py b/mediagoblin/tests/test_auth.py index 5bd8bf2c..61503d32 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -93,8 +93,8 @@ def test_register_views(test_app): assert 'mediagoblin/user_pages/user.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'happygirl').first() assert new_user assert new_user.status == u'needs_email_verification' assert new_user.email_verified == False @@ -128,8 +128,8 @@ def test_register_views(test_app): # 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'happygirl').first() assert new_user assert new_user.status == u'needs_email_verification' assert new_user.email_verified == False @@ -142,8 +142,8 @@ 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'happygirl').first() assert new_user assert new_user.status == u'active' assert new_user.email_verified == True diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py index acc638d9..d70d0478 100644 --- a/mediagoblin/tests/test_edit.py +++ b/mediagoblin/tests/test_edit.py @@ -190,8 +190,8 @@ class TestUserEdit(object): assert urlparse.urlsplit(res.location)[2] == '/' # Email shouldn't be saved - email_in_db = mg_globals.database.User.find_one( - {'email': 'new@example.com'}) + 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' diff --git a/mediagoblin/tests/test_openid.py b/mediagoblin/tests/test_openid.py index c85f6318..bba46db8 100644 --- a/mediagoblin/tests/test_openid.py +++ b/mediagoblin/tests/test_openid.py @@ -186,8 +186,8 @@ class TestOpenIDPlugin(object): openid_plugin_app.get('/auth/logout') # Get user and detach from session - test_user = mg_globals.database.User.find_one({ - 'username': u'chris'}) + test_user = mg_globals.database.User.query.filter_by( + username=u'chris').first() Session.expunge(test_user) # Log back in @@ -314,8 +314,8 @@ class TestOpenIDPlugin(object): assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT # OpenID Added? - new_openid = mg_globals.database.OpenIDUserURL.find_one( - {'openid_url': u'http://add.myopenid.com'}) + new_openid = mg_globals.database.OpenIDUserURL.query.filter_by( + openid_url=u'http://add.myopenid.com').first() assert new_openid _test_add() @@ -365,8 +365,8 @@ class TestOpenIDPlugin(object): assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT # OpenID deleted? - new_openid = mg_globals.database.OpenIDUserURL.find_one( - {'openid_url': u'http://add.myopenid.com'}) + 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_submission.py b/mediagoblin/tests/test_submission.py index 162b2d19..2ac167cb 100644 --- a/mediagoblin/tests/test_submission.py +++ b/mediagoblin/tests/test_submission.py @@ -77,7 +77,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): @@ -122,7 +122,7 @@ class TestSubmission: assert 'mediagoblin/user_pages/user.html' in context 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: @@ -240,8 +240,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' @@ -252,7 +252,7 @@ class TestSubmission: 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}) + 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/tools.py b/mediagoblin/tests/tools.py index 2584c62f..98361adc 100644 --- a/mediagoblin/tests/tools.py +++ b/mediagoblin/tests/tools.py @@ -164,7 +164,7 @@ 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 From a4dcb1f46a89f33d4946219b02bce6325fb68e50 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 11 Jul 2013 09:37:38 -0700 Subject: [PATCH 131/153] Patch submitted by mrb. Fix to link to the pubsub hub for atom_feed 'by tag'. Added 'rel': 'alternate' and 'type': 'text/html' to 'atomlinks' --- mediagoblin/listings/views.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) 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 . +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, From 527b7e3b57906a86dae914daae0399b04b3b5388 Mon Sep 17 00:00:00 2001 From: Jakob Kramer Date: Fri, 10 May 2013 00:40:13 +0200 Subject: [PATCH 132/153] add login option: stay_logged_in As proposed in issue #354; it adds an attribute max_age to mediagoblin.tools.session.Session that is passed to response.set_cookie; max_age is set to 30 days if the checkbox is selected --- mediagoblin/auth/views.py | 2 ++ mediagoblin/plugins/basic_auth/forms.py | 2 ++ mediagoblin/tools/session.py | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 1cff8dcc..d276a074 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -88,6 +88,8 @@ def login(request): if user: # set up login in session + if login_form.stay_logged_in.data: + request.session.max_age = 30 * 24 * 60 * 60 request.session['user_id'] = unicode(user.id) request.session.save() diff --git a/mediagoblin/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py index 72d99dff..0793f5f4 100644 --- a/mediagoblin/plugins/basic_auth/forms.py +++ b/mediagoblin/plugins/basic_auth/forms.py @@ -41,3 +41,5 @@ class LoginForm(wtforms.Form): normalize_user_or_email_field()]) password = wtforms.PasswordField( _('Password')) + stay_logged_in = wtforms.BooleanField( + _('Stay logged in')) diff --git a/mediagoblin/tools/session.py b/mediagoblin/tools/session.py index fdc32523..ccf96443 100644 --- a/mediagoblin/tools/session.py +++ b/mediagoblin/tools/session.py @@ -24,6 +24,7 @@ _log = logging.getLogger(__name__) class Session(dict): def __init__(self, *args, **kwargs): self.send_new_cookie = False + self.max_age = None dict.__init__(self, *args, **kwargs) def save(self): @@ -65,4 +66,4 @@ class SessionManager(object): response.delete_cookie(self.cookie_name) else: response.set_cookie(self.cookie_name, self.signer.dumps(session), - httponly=True) + max_age=session.max_age, httponly=True) From ef57b0622c06d2b169cbe28f5e9f38ebf569badb Mon Sep 17 00:00:00 2001 From: Jakob Kramer Date: Wed, 22 May 2013 14:51:12 +0200 Subject: [PATCH 133/153] =?UTF-8?q?save=20=E2=80=9Cstay=5Flogged=5Fin?= =?UTF-8?q?=E2=80=9D=20in=20the=20session?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since sessions are rebuilt, e.g. when you try to post a blank comment and therefore receive an error message, the session will be overwritten without the old max_age. --- mediagoblin/auth/views.py | 2 +- mediagoblin/tools/session.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index d276a074..d54762b0 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -89,7 +89,7 @@ def login(request): if user: # set up login in session if login_form.stay_logged_in.data: - request.session.max_age = 30 * 24 * 60 * 60 + request.session['stay_logged_in'] = True request.session['user_id'] = unicode(user.id) request.session.save() diff --git a/mediagoblin/tools/session.py b/mediagoblin/tools/session.py index ccf96443..d79afb66 100644 --- a/mediagoblin/tools/session.py +++ b/mediagoblin/tools/session.py @@ -21,10 +21,11 @@ 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 - self.max_age = None dict.__init__(self, *args, **kwargs) def save(self): @@ -65,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), - max_age=session.max_age, httponly=True) + max_age=max_age, httponly=True) From 0ec7ce4ec684ebeb205e7dfa3f3f08a814074297 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Tue, 25 Jun 2013 16:37:28 -0700 Subject: [PATCH 134/153] updated to new render_divs macro --- mediagoblin/plugins/basic_auth/forms.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mediagoblin/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py index 0793f5f4..6cf01b38 100644 --- a/mediagoblin/plugins/basic_auth/forms.py +++ b/mediagoblin/plugins/basic_auth/forms.py @@ -42,4 +42,5 @@ class LoginForm(wtforms.Form): password = wtforms.PasswordField( _('Password')) stay_logged_in = wtforms.BooleanField( - _('Stay logged in')) + label='', + description=_('Stay logged in')) From f7998c3326d7c2ed06a978f721cf6533fbde1c15 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 08:29:03 -0700 Subject: [PATCH 135/153] fix for boolean fields --- mediagoblin/edit/forms.py | 1 - mediagoblin/static/css/base.css | 4 ++ .../templates/mediagoblin/utils/wtforms.html | 47 ++++++++++++------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py index e0147a0c..85c243a0 100644 --- a/mediagoblin/edit/forms.py +++ b/mediagoblin/edit/forms.py @@ -66,7 +66,6 @@ class EditAccountForm(wtforms.Form): [wtforms.validators.Optional(), normalize_user_or_email_field(allow_user=False)]) wants_comment_notification = wtforms.BooleanField( - label='', description=_("Email me when others comment on my media")) license_preference = wtforms.SelectField( _('License preference'), diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css index 8b57584d..995bfc7e 100644 --- a/mediagoblin/static/css/base.css +++ b/mediagoblin/static/css/base.css @@ -334,6 +334,10 @@ text-align: center; width: 20px; } +#boolean { + margin-bottom: 4px; + } + textarea#description, textarea#bio { resize: vertical; height: 100px; diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html index a4c33f1a..2b2cc30a 100644 --- a/mediagoblin/templates/mediagoblin/utils/wtforms.html +++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html @@ -34,26 +34,26 @@ {# Generically render a field #} {% macro render_field_div(field, autofocus_first=False) %} - {{- render_label_p(field) }} -
- {% if autofocus_first %} - {{ field(autofocus=True) }} - {% else %} - {{ field }} - {% endif %} - {%- if field.errors -%} - {% for error in field.errors %} -

{{ error }}

- {% endfor %} - {%- endif %} - {%- if field.description %} - {% if field.type == 'BooleanField' %} - + {% if field.type == 'BooleanField' %} + {{ render_bool(field) }} + {% else %} + {{- render_label_p(field) }} +
+ {% if autofocus_first %} + {{ field(autofocus=True) }} {% else %} -

{{ field.description|safe }}

+ {{ field }} {% endif %} - {%- endif %} -
+ {%- if field.errors -%} + {% for error in field.errors %} +

{{ error }}

+ {% endfor %} + {%- endif %} + {%- if field.description %} +

{{ field.description|safe }}

+ {%- endif %} +
+ {% endif %} {%- endmacro %} {# Auto-render a form as a series of divs #} @@ -86,3 +86,14 @@ {% endfor %} {%- endmacro %} + +{# Render a boolean field #} +{% macro render_bool(field) %} +
+ +
+{% endmacro %} + From a937ea9efdfb537be70a152609144c1aac6d3b61 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Wed, 26 Jun 2013 08:45:59 -0700 Subject: [PATCH 136/153] change to class instead of id to work with firefox --- mediagoblin/static/css/base.css | 4 ++-- mediagoblin/templates/mediagoblin/utils/wtforms.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css index 995bfc7e..84d274d1 100644 --- a/mediagoblin/static/css/base.css +++ b/mediagoblin/static/css/base.css @@ -334,8 +334,8 @@ text-align: center; width: 20px; } -#boolean { - margin-bottom: 4px; +.boolean { + margin-bottom: 8px; } textarea#description, textarea#bio { diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html index 2b2cc30a..fe5883a0 100644 --- a/mediagoblin/templates/mediagoblin/utils/wtforms.html +++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html @@ -89,7 +89,7 @@ {# Render a boolean field #} {% macro render_bool(field) %} -
+
{% endmacro %} From 0f231966b34c95b41ca43550011302e5341e5eb2 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Thu, 11 Jul 2013 16:33:33 -0700 Subject: [PATCH 138/153] make change_pass page autofocus --- mediagoblin/templates/mediagoblin/edit/change_pass.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediagoblin/templates/mediagoblin/edit/change_pass.html b/mediagoblin/templates/mediagoblin/edit/change_pass.html index ff909b07..2a1ffee0 100644 --- a/mediagoblin/templates/mediagoblin/edit/change_pass.html +++ b/mediagoblin/templates/mediagoblin/edit/change_pass.html @@ -39,7 +39,7 @@ Changing {{ username }}'s password {%- endtrans -%} - {{ wtforms_util.render_divs(form) }} + {{ wtforms_util.render_divs(form, True) }} {{ csrf_token }}
Date: Fri, 12 Jul 2013 09:32:50 -0700 Subject: [PATCH 139/153] Patch by pythonsnake. Make mediagoblin.ini comments more helpful. --- mediagoblin.ini | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mediagoblin.ini b/mediagoblin.ini index e878a478..043e7312 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". +## 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 -## You may have to install dependencies, and will have to run ./bin/gmg dbupdate +## You may have to install dependencies, and will have to run `./bin/gmg dbupdate` ## See http://docs.mediagoblin.org/siteadmin/media-types.html for details. # media_types = mediagoblin.media_types.image, mediagoblin.media_types.video @@ -43,8 +44,8 @@ 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]] From ac08a9acaffbafdcb99506495a192b1eaa508544 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 12 Jul 2013 09:51:42 -0700 Subject: [PATCH 140/153] Patch by Strum. Remove redundent tool-tips from Stl media_type --- .../mediagoblin/media_displays/stl.html | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) 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 () {
- + {%- trans %}Perspective{% endtrans -%} - + {%- trans %}Front{% endtrans -%} - + {%- trans %}Top{% endtrans -%} - + {%- trans %}Side{% endtrans -%} {% if media.media_data.file_type == "stl" %} + onclick="show_things();"> {%- trans %}WebGL{% endtrans -%} {% endif %} {%- trans %}Download model{% endtrans -%} From 003ea47499a3f4ed0be2d5ad49e7a0ce8bb62278 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 12 Jul 2013 14:16:47 -0500 Subject: [PATCH 141/153] Changing the information spat out while printing from media types->plugins Previously it called even plugins media types. Ha! This commit sponsored by Jon Merkley. Thank you! --- mediagoblin/db/migration_tools.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mediagoblin/db/migration_tools.py b/mediagoblin/db/migration_tools.py index c0c7e998..aa22ef94 100644 --- a/mediagoblin/db/migration_tools.py +++ b/mediagoblin/db/migration_tools.py @@ -175,8 +175,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): """ From 60eeb4566457a127c7783e9ac7953daebf3e4592 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 12 Jul 2013 14:53:10 -0500 Subject: [PATCH 142/153] Switch the import of the image media manager over to the new class This helps resolve one of the remaining issues with the tests for the media type pluginification. This commit sponsored by Jeffrey Moe. Thanks Jeff! Lulzbot rocks! --- mediagoblin/tests/test_submission.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py index 162b2d19..dd7db12a 100644 --- a/mediagoblin/tests/test_submission.py +++ b/mediagoblin/tests/test_submission.py @@ -26,7 +26,7 @@ from mediagoblin.tests.tools import fixture_add_user from mediagoblin import mg_globals from mediagoblin.db.models import MediaEntry 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, \ @@ -219,7 +219,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 From 4259ad5bf1680896090290e7327b49a053a8447b Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 12 Jul 2013 15:52:20 -0500 Subject: [PATCH 143/153] Fix the last bit preventing all the unit tests from passing in media types->plugins The last commit was also small, so Jeff Moe gets... two! Two sponsored commits! Ah ah ah. --- mediagoblin/db/mixin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index 26e41a3b..ee8525c2 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -205,7 +205,8 @@ class MediaEntryMixin(GenerateSlugMixin): """ manager = hook_handle('get_media_manager', self.media_type) if manager: - return manager + return manager(self) + # Not found? Then raise an error raise FileTypeNotSupported( "MediaManager not in enabled types. Check media_type plugins are" From 91bee92e8ef188e4a5aa191b6c047a57a668f5fa Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Fri, 12 Jul 2013 11:57:16 -0700 Subject: [PATCH 144/153] documenting the new media_type plugins and available hooks --- docs/source/index.rst | 1 + docs/source/pluginwriter/media_type_hooks.rst | 27 ++++++++++++++ docs/source/siteadmin/media-types.rst | 37 +++++++++---------- 3 files changed, 46 insertions(+), 19 deletions(-) create mode 100644 docs/source/pluginwriter/media_type_hooks.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index c8a3f040..de6c9c0d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -74,6 +74,7 @@ This guide covers writing new GNU MediaGoblin plugins. pluginwriter/database pluginwriter/api pluginwriter/tests + pluginwriter/media_type_hooks Part 4: Developer's Zone diff --git a/docs/source/pluginwriter/media_type_hooks.rst b/docs/source/pluginwriter/media_type_hooks.rst new file mode 100644 index 00000000..0dfbbafd --- /dev/null +++ b/docs/source/pluginwriter/media_type_hooks.rst @@ -0,0 +1,27 @@ +================== + 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. diff --git a/docs/source/siteadmin/media-types.rst b/docs/source/siteadmin/media-types.rst index 1527bc70..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 @@ -233,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 From 6403bc928bbdd916248775580d1bfa90c511f2dc Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 12 Jul 2013 17:04:08 -0500 Subject: [PATCH 145/153] Switching the hook 'get_media_manager' to a more "directed" tuple-hook By switching this to a tuple that includes the media type in the key itself, this requires iteration and execution of functions that "check" that they are the right type. This commit sponsored by Greg Grossmeier. Thanks buddy! :) --- mediagoblin/db/mixin.py | 2 +- mediagoblin/media_types/__init__.py | 2 +- mediagoblin/media_types/ascii/__init__.py | 7 +------ mediagoblin/media_types/audio/__init__.py | 7 +------ mediagoblin/media_types/image/__init__.py | 7 +------ mediagoblin/media_types/pdf/__init__.py | 8 ++------ mediagoblin/media_types/stl/__init__.py | 7 +------ mediagoblin/media_types/video/__init__.py | 7 +------ 8 files changed, 9 insertions(+), 38 deletions(-) diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py index ee8525c2..57b27d83 100644 --- a/mediagoblin/db/mixin.py +++ b/mediagoblin/db/mixin.py @@ -203,7 +203,7 @@ class MediaEntryMixin(GenerateSlugMixin): Raises FileTypeNotSupported in case no such manager is enabled """ - manager = hook_handle('get_media_manager', self.media_type) + manager = hook_handle(('media_manager', self.media_type)) if manager: return manager(self) diff --git a/mediagoblin/media_types/__init__.py b/mediagoblin/media_types/__init__.py index 395ba17a..134157dc 100644 --- a/mediagoblin/media_types/__init__.py +++ b/mediagoblin/media_types/__init__.py @@ -69,7 +69,7 @@ def sniff_media(media): media_type = hook_handle('sniff_handler', media_file, media=media) if media_type: _log.info('{0} accepts the file'.format(media_type)) - return media_type, hook_handle('get_media_managers', media_type) + return media_type, hook_handle(('media_manager', media_type)) else: _log.debug('{0} did not accept the file'.format(media_type)) diff --git a/mediagoblin/media_types/ascii/__init__.py b/mediagoblin/media_types/ascii/__init__.py index bcba237c..4baf8dd3 100644 --- a/mediagoblin/media_types/ascii/__init__.py +++ b/mediagoblin/media_types/ascii/__init__.py @@ -34,11 +34,6 @@ class ASCIIMediaManager(MediaManagerBase): default_thumb = "images/media_thumbs/ascii.jpg" -def get_media_manager(media_type): - if media_type == MEDIA_TYPE: - return ASCIIMediaManager - - def get_media_type_and_manager(ext): if ext in ACCEPTED_EXTENSIONS: return MEDIA_TYPE, ASCIIMediaManager @@ -47,6 +42,6 @@ def get_media_type_and_manager(ext): hooks = { 'setup': setup_plugin, 'get_media_type_and_manager': get_media_type_and_manager, + ('media_manager', MEDIA_TYPE): lambda: ASCIIMediaManager, 'sniff_handler': sniff_handler, - 'get_media_manager': get_media_manager, } diff --git a/mediagoblin/media_types/audio/__init__.py b/mediagoblin/media_types/audio/__init__.py index dfe68660..90f842ba 100644 --- a/mediagoblin/media_types/audio/__init__.py +++ b/mediagoblin/media_types/audio/__init__.py @@ -33,11 +33,6 @@ class AudioMediaManager(MediaManagerBase): display_template = "mediagoblin/media_displays/audio.html" -def get_media_manager(media_type): - if media_type == MEDIA_TYPE: - return AudioMediaManager - - def get_media_type_and_manager(ext): if ext in ACCEPTED_EXTENSIONS: return MEDIA_TYPE, AudioMediaManager @@ -46,5 +41,5 @@ hooks = { 'setup': setup_plugin, 'get_media_type_and_manager': get_media_type_and_manager, 'sniff_handler': sniff_handler, - 'get_media_manager': get_media_manager, + ('media_manager', MEDIA_TYPE): lambda: AudioMediaManager, } diff --git a/mediagoblin/media_types/image/__init__.py b/mediagoblin/media_types/image/__init__.py index 4b991588..1bb9c6f3 100644 --- a/mediagoblin/media_types/image/__init__.py +++ b/mediagoblin/media_types/image/__init__.py @@ -59,11 +59,6 @@ class ImageMediaManager(MediaManagerBase): return None -def get_media_manager(media_type): - if media_type == MEDIA_TYPE: - return ImageMediaManager - - def get_media_type_and_manager(ext): if ext in ACCEPTED_EXTENSIONS: return MEDIA_TYPE, ImageMediaManager @@ -73,5 +68,5 @@ hooks = { 'setup': setup_plugin, 'get_media_type_and_manager': get_media_type_and_manager, 'sniff_handler': sniff_handler, - 'get_media_manager': get_media_manager, + ('media_manager', MEDIA_TYPE): lambda: ImageMediaManager, } diff --git a/mediagoblin/media_types/pdf/__init__.py b/mediagoblin/media_types/pdf/__init__.py index c180507c..67509ddc 100644 --- a/mediagoblin/media_types/pdf/__init__.py +++ b/mediagoblin/media_types/pdf/__init__.py @@ -34,18 +34,14 @@ class PDFMediaManager(MediaManagerBase): default_thumb = "images/media_thumbs/pdf.jpg" -def get_media_manager(media_type): - if media_type == MEDIA_TYPE: - return PDFMediaManager - - def get_media_type_and_manager(ext): if ext in ACCEPTED_EXTENSIONS: return MEDIA_TYPE, PDFMediaManager + hooks = { 'setup': setup_plugin, 'get_media_type_and_manager': get_media_type_and_manager, 'sniff_handler': sniff_handler, - 'get_media_manager': get_media_manager, + ('media_manager', MEDIA_TYPE): lambda: PDFMediaManager, } diff --git a/mediagoblin/media_types/stl/__init__.py b/mediagoblin/media_types/stl/__init__.py index 192b5761..1d2a8478 100644 --- a/mediagoblin/media_types/stl/__init__.py +++ b/mediagoblin/media_types/stl/__init__.py @@ -34,11 +34,6 @@ class STLMediaManager(MediaManagerBase): default_thumb = "images/media_thumbs/video.jpg" -def get_media_manager(media_type): - if media_type == MEDIA_TYPE: - return STLMediaManager - - def get_media_type_and_manager(ext): if ext in ACCEPTED_EXTENSIONS: return MEDIA_TYPE, STLMediaManager @@ -47,5 +42,5 @@ hooks = { 'setup': setup_plugin, 'get_media_type_and_manager': get_media_type_and_manager, 'sniff_handler': sniff_handler, - 'get_media_manager': get_media_manager, + ('media_manager', MEDIA_TYPE): lambda: STLMediaManager, } diff --git a/mediagoblin/media_types/video/__init__.py b/mediagoblin/media_types/video/__init__.py index aa4cdb93..e8a4308b 100644 --- a/mediagoblin/media_types/video/__init__.py +++ b/mediagoblin/media_types/video/__init__.py @@ -39,11 +39,6 @@ class VideoMediaManager(MediaManagerBase): default_webm_type = 'video/webm; codecs="vp8, vorbis"' -def get_media_manager(media_type): - if media_type == MEDIA_TYPE: - return VideoMediaManager - - def get_media_type_and_manager(ext): if ext in ACCEPTED_EXTENSIONS: return MEDIA_TYPE, VideoMediaManager @@ -52,5 +47,5 @@ hooks = { 'setup': setup_plugin, 'get_media_type_and_manager': get_media_type_and_manager, 'sniff_handler': sniff_handler, - 'get_media_manager': get_media_manager, + ('media_manager', MEDIA_TYPE): lambda: VideoMediaManager, } From 2d0028e93283fea397133294a5eb45b67d5ed0ab Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Fri, 12 Jul 2013 17:13:48 -0500 Subject: [PATCH 146/153] Documenting the media_manager fetching hook This commit sponsored by Christian Corrodi. Thank you! --- docs/source/pluginwriter/media_type_hooks.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/source/pluginwriter/media_type_hooks.rst b/docs/source/pluginwriter/media_type_hooks.rst index 0dfbbafd..498b0b54 100644 --- a/docs/source/pluginwriter/media_type_hooks.rst +++ b/docs/source/pluginwriter/media_type_hooks.rst @@ -25,3 +25,14 @@ 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. From df206ab633ef369c89d27321823daf140a5ff6f4 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 14 Jul 2013 11:23:52 -0500 Subject: [PATCH 147/153] Skip the openid tests if the openid module is not installed. This commit sponsored by Brandon Smith. Thank you! --- mediagoblin/tests/test_openid.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mediagoblin/tests/test_openid.py b/mediagoblin/tests/test_openid.py index bba46db8..23a2290e 100644 --- a/mediagoblin/tests/test_openid.py +++ b/mediagoblin/tests/test_openid.py @@ -13,12 +13,14 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . + import urlparse import pkg_resources import pytest import mock -from openid.consumer.consumer import SuccessResponse +openid_consumer = pytest.importorskip( + "openid.consumer.consumer") from mediagoblin import mg_globals from mediagoblin.db.base import Session @@ -27,7 +29,6 @@ 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): @@ -41,7 +42,7 @@ def openid_plugin_app(request): class TestOpenIDPlugin(object): def _setup(self, openid_plugin_app, value=True, edit=False, delete=False): if value: - response = SuccessResponse(mock.Mock(), mock.Mock()) + response = openid_consumer.SuccessResponse(mock.Mock(), mock.Mock()) if edit or delete: response.identity_url = u'http://add.myopenid.com' else: From 64ad0beea83b1f4b50462bcb67c54156fc9365a5 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Sun, 14 Jul 2013 21:05:01 -0500 Subject: [PATCH 148/153] Fixing docs: git submodule update, not git submodule fetch! This commit sponsored by Charles Combs. Thank you! --- docs/source/siteadmin/deploying.rst | 2 +- docs/source/siteadmin/relnotes.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/siteadmin/deploying.rst b/docs/source/siteadmin/deploying.rst index 9d7f83c1..751b01c5 100644 --- a/docs/source/siteadmin/deploying.rst +++ b/docs/source/siteadmin/deploying.rst @@ -160,7 +160,7 @@ directory. Modify these commands to reflect your own environment:: Clone the MediaGoblin repository and set up the git submodules:: git clone git://gitorious.org/mediagoblin/mediagoblin.git - git submodule init && git submodule fetch + git submodule init && git submodule update And set up the in-package virtualenv:: diff --git a/docs/source/siteadmin/relnotes.rst b/docs/source/siteadmin/relnotes.rst index 8e7ba396..35415b66 100644 --- a/docs/source/siteadmin/relnotes.rst +++ b/docs/source/siteadmin/relnotes.rst @@ -63,7 +63,7 @@ Otherwise, follow 0.4.0 instructions. 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 fetch`` + ``git submodule init && git submodule update`` You will need to do this to use the new PDF support. **For theme authors** From b889f97156ecb9dc1d72cd8d52a21245e0d28834 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Tue, 23 Jul 2013 20:24:30 -0500 Subject: [PATCH 149/153] Move the "cd mediagoblin" to the right line. Thanks usrnix! This commit sponsored by Kenneth Dombrowski. Thanks! --- docs/source/siteadmin/deploying.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/siteadmin/deploying.rst b/docs/source/siteadmin/deploying.rst index 751b01c5..50fc05c5 100644 --- a/docs/source/siteadmin/deploying.rst +++ b/docs/source/siteadmin/deploying.rst @@ -160,11 +160,11 @@ directory. Modify these commands to reflect your own environment:: 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:: From 9a2b36c9a2671938f37c642c2414f5a11b7e74f4 Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Thu, 25 Jul 2013 14:05:50 -0500 Subject: [PATCH 150/153] More up to date README --- README | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README b/README index 07f9a094..98b8e9e9 100644 --- a/README +++ b/README @@ -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? From 130b85f81ac297ebb769ab133c8adb1647d794a8 Mon Sep 17 00:00:00 2001 From: Rodney Ewing Date: Mon, 29 Jul 2013 11:25:34 -0700 Subject: [PATCH 151/153] babel 1.0 doesn't have a localedata.list() method, so updated setup.py. made "import crypto" fully qualified --- mediagoblin/tools/session.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediagoblin/tools/session.py b/mediagoblin/tools/session.py index d79afb66..a57f69cc 100644 --- a/mediagoblin/tools/session.py +++ b/mediagoblin/tools/session.py @@ -17,7 +17,7 @@ import itsdangerous import logging -import crypto +from mediagoblin.tools import crypto _log = logging.getLogger(__name__) diff --git a/setup.py b/setup.py index 6e026f30..14a9a24f 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ setup( 'kombu==2.1.7', 'jinja2', 'sphinx', - 'Babel', + 'Babel<1.0', 'argparse', 'webtest<2', 'ConfigObj', From f2b2008da51ff554df1af0e5a14a73aff4d89c33 Mon Sep 17 00:00:00 2001 From: tilly-Q Date: Mon, 29 Jul 2013 16:36:06 -0400 Subject: [PATCH 152/153] This was a very simple ticket actually. I created a list called FOUNDATIONS in mediagoblin/db/models.py. This list holds all of the information about rows that should be created at database initialization. Read the documentation near the FOUNDATIONS list to understand the proper format for this list. All of the work is done through a new method on MigrationManager in mediagoblin/db/migrations_tools.py. This method, `populate_table_foundations` parses the FOUNDATIONS list and creates the foundations based on the data incl- uded. This only ever happens when the database is initialized. Migrations to releases with new Foundations should be very easy just using the basic database functionality. --- mediagoblin/db/migration_tools.py | 16 +++++++++++++++- mediagoblin/db/models.py | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mediagoblin/db/migration_tools.py b/mediagoblin/db/migration_tools.py index aa22ef94..1192836d 100644 --- a/mediagoblin/db/migration_tools.py +++ b/mediagoblin/db/migration_tools.py @@ -140,6 +140,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 + """ + from mediagoblin.db.models import FOUNDATIONS as MAIN_FOUNDATIONS + for Model, rows in MAIN_FOUNDATIONS.items(): + print u'\n--> Laying foundations for %s table' % Model.__name__ + for parameters in rows: + row = Model(**parameters) + row.save() + def create_new_migration_record(self): """ Create a new migration record for this migration set @@ -202,7 +214,9 @@ class MigrationManager(object): self.init_tables() # auto-set at latest migration number - self.create_new_migration_record() + self.create_new_migration_record() + if self.name==u'__main__': + self.populate_table_foundations() self.printer(u"done.\n") self.set_current_migration() diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 826d47ba..7448f5ce 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -585,6 +585,21 @@ MODELS = [ Notification, CommentNotification, ProcessingNotification, CommentSubscription] +""" + 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} +""" +FOUNDATIONS = {} ###################################################### # Special, migrations-tracking table From 08cd10d84fd89df3f0cad3835ba8ab8b8000d4b2 Mon Sep 17 00:00:00 2001 From: tilly-Q Date: Mon, 29 Jul 2013 17:15:29 -0400 Subject: [PATCH 153/153] I actually had to do a bit more work than I thought, because I needed to account for plugins. In this commit I changed the MigrationManager and DatabaseData ob- jects to account for FOUNDATIONS in any plugin's (or main program's) models.py file. --- mediagoblin/db/migration_tools.py | 15 +++++++-------- mediagoblin/gmg_commands/dbupdate.py | 25 ++++++++++++++++++++----- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/mediagoblin/db/migration_tools.py b/mediagoblin/db/migration_tools.py index 1192836d..ad137683 100644 --- a/mediagoblin/db/migration_tools.py +++ b/mediagoblin/db/migration_tools.py @@ -29,7 +29,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 +40,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 @@ -145,12 +146,11 @@ class MigrationManager(object): Create the table foundations (default rows) as layed out in FOUNDATIONS in mediagoblin.db.models """ - from mediagoblin.db.models import FOUNDATIONS as MAIN_FOUNDATIONS - for Model, rows in MAIN_FOUNDATIONS.items(): - print u'\n--> Laying foundations for %s table' % Model.__name__ + for Model, rows in self.foundations.items(): + print u'\n + Laying foundations for %s table' % (Model.__name__) for parameters in rows: - row = Model(**parameters) - row.save() + new_row = Model(**parameters) + new_row.save() def create_new_migration_record(self): """ @@ -215,8 +215,7 @@ class MigrationManager(object): self.init_tables() # auto-set at latest migration number self.create_new_migration_record() - if self.name==u'__main__': - self.populate_table_foundations() + self.populate_table_foundations() self.printer(u"done.\n") self.set_current_migration() diff --git a/mediagoblin/gmg_commands/dbupdate.py b/mediagoblin/gmg_commands/dbupdate.py index 00007567..bad3e352 100644 --- a/mediagoblin/gmg_commands/dbupdate.py +++ b/mediagoblin/gmg_commands/dbupdate.py @@ -32,14 +32,15 @@ def dbupdate_parse_setup(subparser): 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(plugins): @@ -54,10 +55,11 @@ def gather_database_data(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)) + u'__main__', MAIN_MODELS, MAIN_FOUNDATIONS, MAIN_MIGRATIONS)) for plugin in plugins: try: @@ -83,13 +85,26 @@ 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: + _log.debug('No foundations found for {0}: {1}'.format( + plugin, + exc)) + + foundations = [] + except AttributeError as exc: + _log.debug('Could not find FOUNDATIONS in {0}.models, have you \ +forgotten to add it? ({1})'.format(plugin, exc)) + foundations = {} + if models: managed_dbdata.append( - DatabaseData(plugin, models, migrations)) + DatabaseData(plugin, models, foundations, migrations)) return managed_dbdata