'
+ link = url_prefix + user.get_profile_url() + '?sort=email_subscriptions'
+ text += _('go to %(link)s to change frequency of email updates or %(email)s administrator') \
+ % {'link':link, 'email':settings.ADMINS[0][1]}
+ msg = EmailMessage(subject, text, settings.DEFAULT_FROM_EMAIL, [user.email])
+ msg.content_subtype = 'html'
+ msg.send()
diff --git a/forum/management/commands/subscribe_everyone.py b/forum/management/commands/subscribe_everyone.py
new file mode 100644
index 00000000..3f8da9ec
--- /dev/null
+++ b/forum/management/commands/subscribe_everyone.py
@@ -0,0 +1,31 @@
+from django.core.management.base import NoArgsCommand
+from django.db import connection
+from django.db.models import Q, F
+from forum.models import *
+from django.core.mail import EmailMessage
+from django.utils.translation import ugettext as _
+from django.utils.translation import ungettext
+import datetime
+import settings
+
+class Command(NoArgsCommand):
+ def handle_noargs(self,**options):
+ try:
+ self.subscribe_everyone()
+ except Exception, e:
+ print e
+ finally:
+ connection.close()
+
+ def subscribe_everyone(self):
+
+ feed_type_info = EmailFeedSetting.FEED_TYPES
+ for user in User.objects.all():
+ for feed_type in feed_type_info:
+ try:
+ feed_setting = EmailFeedSetting.objects.get(subscriber=user,feed_type = feed_type[0])
+ except EmailFeedSetting.DoesNotExist:
+ feed_setting = EmailFeedSetting(subscriber=user,feed_type=feed_type[0])
+ feed_setting.frequency = 'w'
+ feed_setting.reported_at = None
+ feed_setting.save()
diff --git a/forum/managers.py b/forum/managers.py
index 6ae0ed99..795d382e 100644
--- a/forum/managers.py
+++ b/forum/managers.py
@@ -70,7 +70,7 @@ class QuestionManager(models.Manager):
# although we have imported all classes from models on top.
from forum.models import Answer
self.filter(id=question.id).update(
- answer_count=Answer.objects.get_answers_from_question(question).count())
+ answer_count=Answer.objects.get_answers_from_question(question).filter(deleted=False).count())
def update_view_count(self, question):
"""
@@ -93,11 +93,11 @@ class QuestionManager(models.Manager):
"""
#print datetime.datetime.now()
from forum.models import Question
- questions = list(Question.objects.filter(tagnames = question.tagnames).all())
+ questions = list(Question.objects.filter(tagnames = question.tagnames, deleted=False).all())
tags_list = question.tags.all()
for tag in tags_list:
- extend_questions = Question.objects.filter(tags__id = tag.id)[:50]
+ extend_questions = Question.objects.filter(tags__id = tag.id, deleted=False)[:50]
for item in extend_questions:
if item not in questions and len(questions) < 10:
questions.append(item)
@@ -110,10 +110,11 @@ class TagManager(models.Manager):
'UPDATE tag '
'SET used_count = ('
'SELECT COUNT(*) FROM question_tags '
- 'WHERE tag_id = tag.id'
+ 'INNER JOIN question ON question_id=question.id '
+ 'WHERE tag_id = tag.id AND question.deleted=0'
') '
'WHERE id IN (%s)')
-
+
def get_valid_tags(self, page_size):
from forum.models import Tag
tags = Tag.objects.all().filter(deleted=False).exclude(used_count=0).order_by("-id")[:page_size]
diff --git a/forum/models.py b/forum/models.py
index f647ba12..39058bea 100644
--- a/forum/models.py
+++ b/forum/models.py
@@ -2,7 +2,7 @@
import datetime
import hashlib
from urllib import quote_plus, urlencode
-from django.db import models
+from django.db import models, IntegrityError
from django.utils.html import strip_tags
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
@@ -11,33 +11,61 @@ from django.contrib.contenttypes.models import ContentType
from django.template.defaultfilters import slugify
from django.db.models.signals import post_delete, post_save, pre_save
from django.utils.translation import ugettext as _
+from django.utils.safestring import mark_safe
import django.dispatch
import settings
from forum.managers import *
from const import *
-class EmailFeed(models.Model):
- #subscription key for unsubscribe by visiting emailed link
- key = models.CharField(max_length=32)
- #generic relation with feed content (i.e. question or tags)
- feed_content_type = models.ForeignKey(ContentType,related_name='content_emailfeed')
- feed_id = models.PositiveIntegerField()
- content = generic.GenericForeignKey('feed_content_type','feed_id')
- #generic relation with owner - either nameless email or User
- subscriber_content_type = models.ForeignKey(ContentType,related_name='subscriber_emailfeed')
- subscriber_id = models.PositiveIntegerField()
- subscriber = generic.GenericForeignKey('subscriber_content_type','subscriber_id')
- added_at = models.DateTimeField(default=datetime.datetime.now)
- reported_at = models.DateTimeField(default=datetime.datetime.now)
-
- #getter functions rely on implementations of similar functions in content
- #of subscriber objects
- def get_update_summary(self):
- return self.content.get_update_summary(last_reported_at = self.reported_at,recipient_email = self.get_email())
-
- def get_email(self):
- return self.subscriber.email
+def get_object_comments(self):
+ comments = self.comments.all().order_by('id')
+ return comments
+
+def post_get_last_update_info(self):
+ when = self.added_at
+ who = self.author
+ if self.last_edited_at and self.last_edited_at > when:
+ when = self.last_edited_at
+ who = self.last_edited_by
+ comments = self.comments.all()
+ if len(comments) > 0:
+ for c in comments:
+ if c.added_at > when:
+ when = c.added_at
+ who = c.user
+ return when, who
+
+class EmailFeedSetting(models.Model):
+ DELTA_TABLE = {
+ 'w':datetime.timedelta(7),
+ 'd':datetime.timedelta(1),
+ 'n':datetime.timedelta(-1),
+ }
+ FEED_TYPES = (
+ ('q_all',_('Entire forum')),
+ ('q_ask',_('Questions that I asked')),
+ ('q_ans',_('Questions that I answered')),
+ ('q_sel',_('Individually selected questions')),
+ )
+ UPDATE_FREQUENCY = (
+ ('w',_('Weekly')),
+ ('d',_('Daily')),
+ ('n',_('No email')),
+ )
+ subscriber = models.ForeignKey(User)
+ feed_type = models.CharField(max_length=16,choices=FEED_TYPES)
+ frequency = models.CharField(max_length=8,choices=UPDATE_FREQUENCY,default='n')
+ added_at = models.DateTimeField(auto_now_add=True)
+ reported_at = models.DateTimeField(null=True)
+
+ def save(self,*args,**kwargs):
+ type = self.feed_type
+ subscriber = self.subscriber
+ similar = self.__class__.objects.filter(feed_type=type,subscriber=subscriber).exclude(pk=self.id)
+ if len(similar) > 0:
+ raise IntegrityError('email feed setting already exists')
+ super(EmailFeedSetting,self).save(*args,**kwargs)
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
@@ -45,7 +73,6 @@ class Tag(models.Model):
deleted = models.BooleanField(default=False)
deleted_at = models.DateTimeField(null=True, blank=True)
deleted_by = models.ForeignKey(User, null=True, blank=True, related_name='deleted_tags')
- email_feeds = generic.GenericRelation(EmailFeed)
# Denormalised data
used_count = models.PositiveIntegerField(default=0)
@@ -136,6 +163,7 @@ class Question(models.Model):
locked = models.BooleanField(default=False)
locked_by = models.ForeignKey(User, null=True, blank=True, related_name='locked_questions')
locked_at = models.DateTimeField(null=True, blank=True)
+ followed_by = models.ManyToManyField(User, related_name='followed_questions')
# Denormalised data
score = models.IntegerField(default=0)
vote_up_count = models.IntegerField(default=0)
@@ -155,7 +183,6 @@ class Question(models.Model):
comments = generic.GenericRelation(Comment)
votes = generic.GenericRelation(Vote)
flagged_items = generic.GenericRelation(FlaggedItem)
- email_feeds = generic.GenericRelation(EmailFeed)
objects = QuestionManager()
@@ -212,6 +239,22 @@ class Question(models.Model):
def get_latest_revision(self):
return self.revisions.all()[0]
+ get_comments = get_object_comments
+
+ def get_last_update_info(self):
+
+ when, who = post_get_last_update_info(self)
+
+ answers = self.answers.all()
+ if len(answers) > 0:
+ for a in answers:
+ a_when, a_who = a.get_last_update_info()
+ if a_when > when:
+ when = a_when
+ who = a_who
+
+ return when, who
+
def get_update_summary(self,last_reported_at=None,recipient_email=''):
edited = False
if self.last_edited_at and self.last_edited_at > last_reported_at:
@@ -240,7 +283,7 @@ class Question(models.Model):
answer_comments.append(comment)
#create the report
- if edited or comments or new_answers or modified_answers or answer_comments:
+ if edited or new_answers or modified_answers or answer_comments:
out = []
if edited:
out.append(_('%(author)s modified the question') % {'author':self.last_edited_by.username})
@@ -274,6 +317,11 @@ class Question(models.Model):
class Meta:
db_table = u'question'
+class QuestionView(models.Model):
+ question = models.ForeignKey(Question, related_name='viewed')
+ who = models.ForeignKey(User, related_name='question_views')
+ when = models.DateTimeField()
+
class FavoriteQuestion(models.Model):
"""A favorite Question of a User."""
question = models.ForeignKey(Question)
@@ -303,7 +351,8 @@ class QuestionRevision(models.Model):
return self.question.title
def get_absolute_url(self):
- return '/%s%s/%s' % (_('questions/'),self.question.id,_('revisions'))
+ print 'in QuestionRevision.get_absolute_url()'
+ return reverse('question_revisions', args=[self.question.id])
def save(self, **kwargs):
"""Looks up the next available revision number."""
@@ -383,6 +432,9 @@ class Answer(models.Model):
objects = AnswerManager()
+ get_comments = get_object_comments
+ get_last_update_info = post_get_last_update_info
+
def get_user_vote(self, user):
votes = self.votes.filter(user=user)
if votes.count() > 0:
@@ -397,7 +449,7 @@ class Answer(models.Model):
return self.question.title
def get_absolute_url(self):
- return '%s%s#%s' % (reverse('question', args=[self.question.id]), self.question.title, self.id)
+ return '%s%s#%s' % (reverse('question', args=[self.question.id]), slugify(self.question.title), self.id)
class Meta:
db_table = u'answer'
@@ -415,7 +467,7 @@ class AnswerRevision(models.Model):
text = models.TextField()
def get_absolute_url(self):
- return '/%s%s/%s' % (_('answers/'),self.answer.id,_('revisions'))
+ return reverse('answer_revisions', kwargs={'id':self.answer.id})
def get_question_title(self):
return self.answer.question.title
@@ -538,7 +590,7 @@ class Book(models.Model):
questions = models.ManyToManyField(Question, related_name='book', db_table='book_question')
def get_absolute_url(self):
- return '%s' % reverse('book', args=[self.short_name])
+ return reverse('book', args=[self.short_name])
def __unicode__(self):
return self.title
@@ -577,7 +629,6 @@ class AnonymousEmail(models.Model):
key = models.CharField(max_length=32)
email = models.EmailField(null=False,unique=True)
isvalid = models.BooleanField(default=False)
- feeds = generic.GenericRelation(EmailFeed)
# User extend properties
QUESTIONS_PER_PAGE_CHOICES = (
@@ -586,11 +637,30 @@ QUESTIONS_PER_PAGE_CHOICES = (
(50, u'50'),
)
+def user_is_username_taken(cls,username):
+ try:
+ cls.objects.get(username=username)
+ return True
+ except cls.MultipleObjectsReturned:
+ return True
+ except cls.DoesNotExist:
+ return False
+
+def user_get_q_sel_email_feed_frequency(self):
+ print 'looking for frequency for user %s' % self
+ try:
+ feed_setting = EmailFeedSetting.objects.get(subscriber=self,feed_type='q_sel')
+ except Exception, e:
+ print 'have error %s' % e.message
+ raise e
+ print 'have freq=%s' % feed_setting.frequency
+ return feed_setting.frequency
+
+User.add_to_class('is_approved', models.BooleanField(default=False))
User.add_to_class('email_isvalid', models.BooleanField(default=False))
User.add_to_class('email_key', models.CharField(max_length=32, null=True))
User.add_to_class('reputation', models.PositiveIntegerField(default=1))
User.add_to_class('gravatar', models.CharField(max_length=32))
-User.add_to_class('email_feeds', generic.GenericRelation(EmailFeed))
User.add_to_class('favorite_questions',
models.ManyToManyField(Question, through=FavoriteQuestion,
related_name='favorited_by'))
@@ -608,6 +678,8 @@ User.add_to_class('website', models.URLField(max_length=200, blank=True))
User.add_to_class('location', models.CharField(max_length=100, blank=True))
User.add_to_class('date_of_birth', models.DateField(null=True, blank=True))
User.add_to_class('about', models.TextField(blank=True))
+User.add_to_class('is_username_taken',classmethod(user_is_username_taken))
+User.add_to_class('get_q_sel_email_feed_frequency',user_get_q_sel_email_feed_frequency)
# custom signal
tags_updated = django.dispatch.Signal(providing_args=["question"])
@@ -630,7 +702,14 @@ def delete_messages(self):
def get_profile_url(self):
"""Returns the URL for this User's profile."""
return '%s%s/' % (reverse('user', args=[self.id]), slugify(self.username))
+
+def get_profile_link(self):
+ profile_link = u'%s' % (self.get_profile_url(),self.username)
+ logging.debug('in get profile link %s' % profile_link)
+ return mark_safe(profile_link)
+
User.add_to_class('get_profile_url', get_profile_url)
+User.add_to_class('get_profile_link', get_profile_link)
User.add_to_class('get_messages', get_messages)
User.add_to_class('delete_messages', delete_messages)
diff --git a/forum/templatetags/extra_filters.py b/forum/templatetags/extra_filters.py
index d8b8e61f..3644fdc3 100644
--- a/forum/templatetags/extra_filters.py
+++ b/forum/templatetags/extra_filters.py
@@ -1,5 +1,6 @@
from django import template
from forum import auth
+import logging
register = template.Library()
@@ -8,6 +9,10 @@ register = template.Library()
def collapse(input):
return ' '.join(input.split())
+@register.filter
+def can_moderate_users(user):
+ return auth.can_moderate_users(user)
+
@register.filter
def can_vote_up(user):
return auth.can_vote_up(user)
@@ -17,8 +22,8 @@ def can_flag_offensive(user):
return auth.can_flag_offensive(user)
@register.filter
-def can_add_comments(user):
- return auth.can_add_comments(user)
+def can_add_comments(user,subject):
+ return auth.can_add_comments(user,subject)
@register.filter
def can_vote_down(user):
diff --git a/forum/templatetags/extra_tags.py b/forum/templatetags/extra_tags.py
index 06a2d27c..8bd0e128 100644
--- a/forum/templatetags/extra_tags.py
+++ b/forum/templatetags/extra_tags.py
@@ -1,4 +1,5 @@
import time
+import os
import datetime
import math
import re
@@ -6,13 +7,15 @@ import logging
from django import template
from django.utils.encoding import smart_unicode
from django.utils.safestring import mark_safe
-from django.utils.timesince import timesince
from forum.const import *
+from forum.models import Question, Answer, QuestionRevision, AnswerRevision
from django.utils.translation import ugettext as _
+from django.utils.translation import ungettext
+from django.conf import settings
register = template.Library()
-GRAVATAR_TEMPLATE = ('')
@@ -115,6 +118,23 @@ def cnprog_pagesize(context):
"pagesize" : context["pagesize"],
"is_paginated": context["is_paginated"]
}
+
+@register.inclusion_tag("post_contributor_info.html")
+def post_contributor_info(post,contributor_type='original_author'):
+ """contributor_type: original_author|last_updater
+ """
+ if isinstance(post,Question):
+ post_type = 'question'
+ elif isinstance(post,Answer):
+ post_type = 'answer'
+ elif isinstance(post,AnswerRevision) or isinstance(post,QuestionRevision):
+ post_type = 'revision'
+ return {
+ 'post':post,
+ 'post_type':post_type,
+ 'wiki_on':settings.WIKI_ON,
+ 'contributor_type':contributor_type
+ }
@register.simple_tag
def get_score_badge(user):
@@ -216,20 +236,31 @@ def convert2tagname_list(question):
@register.simple_tag
def diff_date(date, limen=2):
- current_time = datetime.datetime(*time.localtime()[0:6])
- diff = current_time - date
- diff_days = diff.days
- if diff_days > limen:
- return date
+ now = datetime.datetime.now()#datetime(*time.localtime()[0:6])#???
+ diff = now - date
+ days = diff.days
+ hours = int(diff.seconds/3600)
+ minutes = int(diff.seconds/60)
+
+ if days > 2:
+ if date.year == now.year:
+ return date.strftime(_("%b %d at %H:%M"))
+ else:
+ return date.strftime(_("%b %d '%y at %H:%M"))
+ elif days == 2:
+ return _('2 days ago')
+ elif days == 1:
+ return _('yesterday')
+ elif minutes > 60:
+ return ungettext('%(hr)d hour ago','%(hr)d hours ago',hours) % {'hr':hours}
else:
- return timesince(date) + _(' ago')
-
+ return ungettext('%(min)d min ago','%(min)d mins ago',minutes) % {'min':minutes}
+
@register.simple_tag
def get_latest_changed_timestamp():
try:
from time import localtime, strftime
from os import path
- from django.conf import settings
root = settings.SITE_SRC_ROOT
dir = (
root,
@@ -242,3 +273,78 @@ def get_latest_changed_timestamp():
except:
timestr = ''
return timestr
+
+@register.simple_tag
+def href(url):
+ url = '///' + settings.FORUM_SCRIPT_ALIAS + '/' + url
+ return os.path.normpath(url) + '?v=%d' % settings.RESOURCE_REVISION
+
+class ItemSeparatorNode(template.Node):
+ def __init__(self,separator):
+ sep = separator.strip()
+ if sep[0] == sep[-1] and sep[0] in ('\'','"'):
+ sep = sep[1:-1]
+ else:
+ raise template.TemplateSyntaxError('separator in joinitems tag must be quoted')
+ self.content = sep
+ def render(self,context):
+ return self.content
+
+class JoinItemListNode(template.Node):
+ def __init__(self,separator=ItemSeparatorNode("''"), items=()):
+ self.separator = separator
+ self.items = items
+ def render(self,context):
+ out = []
+ empty_re = re.compile(r'^\s*$')
+ for item in self.items:
+ bit = item.render(context)
+ if not empty_re.search(bit):
+ out.append(bit)
+ return self.separator.render(context).join(out)
+
+@register.tag(name="joinitems")
+def joinitems(parser,token):
+ try:
+ tagname,junk,sep_token = token.split_contents()
+ except ValueError:
+ raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters")
+ if junk == 'using':
+ sep_node = ItemSeparatorNode(sep_token)
+ else:
+ raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters")
+ nodelist = []
+ while True:
+ nodelist.append(parser.parse(('separator','endjoinitems')))
+ next = parser.next_token()
+ if next.contents == 'endjoinitems':
+ break
+
+ return JoinItemListNode(separator=sep_node,items=nodelist)
+
+class BlockResourceNode(template.Node):
+ def __init__(self,nodelist):
+ self.items = nodelist
+ def render(self,context):
+ out = '///' + settings.FORUM_SCRIPT_ALIAS
+ if self.items:
+ out += '/'
+ for item in self.items:
+ bit = item.render(context)
+ out += bit
+ out = out.replace(' ','')
+ return os.path.normpath(out) + '?v=%d' % settings.RESOURCE_REVISION
+
+@register.tag(name='blockresource')
+def blockresource(parser,token):
+ try:
+ tagname = token.split_contents()
+ except ValueError:
+ raise template.TemplateSyntaxError("blockresource tag does not use arguments")
+ nodelist = []
+ while True:
+ nodelist.append(parser.parse(('endblockresource')))
+ next = parser.next_token()
+ if next.contents == 'endblockresource':
+ break
+ return BlockResourceNode(nodelist)
diff --git a/forum/templatetags/smart_if.py b/forum/templatetags/smart_if.py
new file mode 100644
index 00000000..a8fc1944
--- /dev/null
+++ b/forum/templatetags/smart_if.py
@@ -0,0 +1,401 @@
+"""
+A smarter {% if %} tag for django templates.
+
+While retaining current Django functionality, it also handles equality,
+greater than and less than operators. Some common case examples::
+
+ {% if articles|length >= 5 %}...{% endif %}
+ {% if "ifnotequal tag" != "beautiful" %}...{% endif %}
+"""
+import unittest
+from django import template
+
+
+register = template.Library()
+
+
+#==============================================================================
+# Calculation objects
+#==============================================================================
+
+class BaseCalc(object):
+ def __init__(self, var1, var2=None, negate=False):
+ self.var1 = var1
+ self.var2 = var2
+ self.negate = negate
+
+ def resolve(self, context):
+ try:
+ var1, var2 = self.resolve_vars(context)
+ outcome = self.calculate(var1, var2)
+ except:
+ outcome = False
+ if self.negate:
+ return not outcome
+ return outcome
+
+ def resolve_vars(self, context):
+ var2 = self.var2 and self.var2.resolve(context)
+ return self.var1.resolve(context), var2
+
+ def calculate(self, var1, var2):
+ raise NotImplementedError()
+
+
+class Or(BaseCalc):
+ def calculate(self, var1, var2):
+ return var1 or var2
+
+
+class And(BaseCalc):
+ def calculate(self, var1, var2):
+ return var1 and var2
+
+
+class Equals(BaseCalc):
+ def calculate(self, var1, var2):
+ return var1 == var2
+
+
+class Greater(BaseCalc):
+ def calculate(self, var1, var2):
+ return var1 > var2
+
+
+class GreaterOrEqual(BaseCalc):
+ def calculate(self, var1, var2):
+ return var1 >= var2
+
+
+class In(BaseCalc):
+ def calculate(self, var1, var2):
+ return var1 in var2
+
+
+#==============================================================================
+# Tests
+#==============================================================================
+
+class TestVar(object):
+ """
+ A basic self-resolvable object similar to a Django template variable. Used
+ to assist with tests.
+ """
+ def __init__(self, value):
+ self.value = value
+
+ def resolve(self, context):
+ return self.value
+
+
+class SmartIfTests(unittest.TestCase):
+ def setUp(self):
+ self.true = TestVar(True)
+ self.false = TestVar(False)
+ self.high = TestVar(9000)
+ self.low = TestVar(1)
+
+ def assertCalc(self, calc, context=None):
+ """
+ Test a calculation is True, also checking the inverse "negate" case.
+ """
+ context = context or {}
+ self.assert_(calc.resolve(context))
+ calc.negate = not calc.negate
+ self.assertFalse(calc.resolve(context))
+
+ def assertCalcFalse(self, calc, context=None):
+ """
+ Test a calculation is False, also checking the inverse "negate" case.
+ """
+ context = context or {}
+ self.assertFalse(calc.resolve(context))
+ calc.negate = not calc.negate
+ self.assert_(calc.resolve(context))
+
+ def test_or(self):
+ self.assertCalc(Or(self.true))
+ self.assertCalcFalse(Or(self.false))
+ self.assertCalc(Or(self.true, self.true))
+ self.assertCalc(Or(self.true, self.false))
+ self.assertCalc(Or(self.false, self.true))
+ self.assertCalcFalse(Or(self.false, self.false))
+
+ def test_and(self):
+ self.assertCalc(And(self.true, self.true))
+ self.assertCalcFalse(And(self.true, self.false))
+ self.assertCalcFalse(And(self.false, self.true))
+ self.assertCalcFalse(And(self.false, self.false))
+
+ def test_equals(self):
+ self.assertCalc(Equals(self.low, self.low))
+ self.assertCalcFalse(Equals(self.low, self.high))
+
+ def test_greater(self):
+ self.assertCalc(Greater(self.high, self.low))
+ self.assertCalcFalse(Greater(self.low, self.low))
+ self.assertCalcFalse(Greater(self.low, self.high))
+
+ def test_greater_or_equal(self):
+ self.assertCalc(GreaterOrEqual(self.high, self.low))
+ self.assertCalc(GreaterOrEqual(self.low, self.low))
+ self.assertCalcFalse(GreaterOrEqual(self.low, self.high))
+
+ def test_in(self):
+ list_ = TestVar([1,2,3])
+ invalid_list = TestVar(None)
+ self.assertCalc(In(self.low, list_))
+ self.assertCalcFalse(In(self.low, invalid_list))
+
+ def test_parse_bits(self):
+ var = IfParser([True]).parse()
+ self.assert_(var.resolve({}))
+ var = IfParser([False]).parse()
+ self.assertFalse(var.resolve({}))
+
+ var = IfParser([False, 'or', True]).parse()
+ self.assert_(var.resolve({}))
+
+ var = IfParser([False, 'and', True]).parse()
+ self.assertFalse(var.resolve({}))
+
+ var = IfParser(['not', False, 'and', 'not', False]).parse()
+ self.assert_(var.resolve({}))
+
+ var = IfParser(['not', 'not', True]).parse()
+ self.assert_(var.resolve({}))
+
+ var = IfParser([1, '=', 1]).parse()
+ self.assert_(var.resolve({}))
+
+ var = IfParser([1, 'not', '=', 1]).parse()
+ self.assertFalse(var.resolve({}))
+
+ var = IfParser([1, 'not', 'not', '=', 1]).parse()
+ self.assert_(var.resolve({}))
+
+ var = IfParser([1, '!=', 1]).parse()
+ self.assertFalse(var.resolve({}))
+
+ var = IfParser([3, '>', 2]).parse()
+ self.assert_(var.resolve({}))
+
+ var = IfParser([1, '<', 2]).parse()
+ self.assert_(var.resolve({}))
+
+ var = IfParser([2, 'not', 'in', [2, 3]]).parse()
+ self.assertFalse(var.resolve({}))
+
+ var = IfParser([1, 'or', 1, '=', 2]).parse()
+ self.assert_(var.resolve({}))
+
+ def test_boolean(self):
+ var = IfParser([True, 'and', True, 'and', True]).parse()
+ self.assert_(var.resolve({}))
+ var = IfParser([False, 'or', False, 'or', True]).parse()
+ self.assert_(var.resolve({}))
+ var = IfParser([True, 'and', False, 'or', True]).parse()
+ self.assert_(var.resolve({}))
+ var = IfParser([False, 'or', True, 'and', True]).parse()
+ self.assert_(var.resolve({}))
+
+ var = IfParser([True, 'and', True, 'and', False]).parse()
+ self.assertFalse(var.resolve({}))
+ var = IfParser([False, 'or', False, 'or', False]).parse()
+ self.assertFalse(var.resolve({}))
+ var = IfParser([False, 'or', True, 'and', False]).parse()
+ self.assertFalse(var.resolve({}))
+ var = IfParser([False, 'and', True, 'or', False]).parse()
+ self.assertFalse(var.resolve({}))
+
+ def test_invalid(self):
+ self.assertRaises(ValueError, IfParser(['not']).parse)
+ self.assertRaises(ValueError, IfParser(['==']).parse)
+ self.assertRaises(ValueError, IfParser([1, 'in']).parse)
+ self.assertRaises(ValueError, IfParser([1, '>', 'in']).parse)
+ self.assertRaises(ValueError, IfParser([1, '==', 'not', 'not']).parse)
+ self.assertRaises(ValueError, IfParser([1, 2]).parse)
+
+
+OPERATORS = {
+ '=': (Equals, True),
+ '==': (Equals, True),
+ '!=': (Equals, False),
+ '>': (Greater, True),
+ '>=': (GreaterOrEqual, True),
+ '<=': (Greater, False),
+ '<': (GreaterOrEqual, False),
+ 'or': (Or, True),
+ 'and': (And, True),
+ 'in': (In, True),
+}
+BOOL_OPERATORS = ('or', 'and')
+
+
+class IfParser(object):
+ error_class = ValueError
+
+ def __init__(self, tokens):
+ self.tokens = tokens
+
+ def _get_tokens(self):
+ return self._tokens
+
+ def _set_tokens(self, tokens):
+ self._tokens = tokens
+ self.len = len(tokens)
+ self.pos = 0
+
+ tokens = property(_get_tokens, _set_tokens)
+
+ def parse(self):
+ if self.at_end():
+ raise self.error_class('No variables provided.')
+ var1 = self.get_bool_var()
+ while not self.at_end():
+ op, negate = self.get_operator()
+ var2 = self.get_bool_var()
+ var1 = op(var1, var2, negate=negate)
+ return var1
+
+ def get_token(self, eof_message=None, lookahead=False):
+ negate = True
+ token = None
+ pos = self.pos
+ while token is None or token == 'not':
+ if pos >= self.len:
+ if eof_message is None:
+ raise self.error_class()
+ raise self.error_class(eof_message)
+ token = self.tokens[pos]
+ negate = not negate
+ pos += 1
+ if not lookahead:
+ self.pos = pos
+ return token, negate
+
+ def at_end(self):
+ return self.pos >= self.len
+
+ def create_var(self, value):
+ return TestVar(value)
+
+ def get_bool_var(self):
+ """
+ Returns either a variable by itself or a non-boolean operation (such as
+ ``x == 0`` or ``x < 0``).
+
+ This is needed to keep correct precedence for boolean operations (i.e.
+ ``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``).
+ """
+ var = self.get_var()
+ if not self.at_end():
+ op_token = self.get_token(lookahead=True)[0]
+ if isinstance(op_token, basestring) and (op_token not in
+ BOOL_OPERATORS):
+ op, negate = self.get_operator()
+ return op(var, self.get_var(), negate=negate)
+ return var
+
+ def get_var(self):
+ token, negate = self.get_token('Reached end of statement, still '
+ 'expecting a variable.')
+ if isinstance(token, basestring) and token in OPERATORS:
+ raise self.error_class('Expected variable, got operator (%s).' %
+ token)
+ var = self.create_var(token)
+ if negate:
+ return Or(var, negate=True)
+ return var
+
+ def get_operator(self):
+ token, negate = self.get_token('Reached end of statement, still '
+ 'expecting an operator.')
+ if not isinstance(token, basestring) or token not in OPERATORS:
+ raise self.error_class('%s is not a valid operator.' % token)
+ if self.at_end():
+ raise self.error_class('No variable provided after "%s".' % token)
+ op, true = OPERATORS[token]
+ if not true:
+ negate = not negate
+ return op, negate
+
+
+#==============================================================================
+# Actual templatetag code.
+#==============================================================================
+
+class TemplateIfParser(IfParser):
+ error_class = template.TemplateSyntaxError
+
+ def __init__(self, parser, *args, **kwargs):
+ self.template_parser = parser
+ return super(TemplateIfParser, self).__init__(*args, **kwargs)
+
+ def create_var(self, value):
+ return self.template_parser.compile_filter(value)
+
+
+class SmartIfNode(template.Node):
+ def __init__(self, var, nodelist_true, nodelist_false=None):
+ self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
+ self.var = var
+
+ def render(self, context):
+ if self.var.resolve(context):
+ return self.nodelist_true.render(context)
+ if self.nodelist_false:
+ return self.nodelist_false.render(context)
+ return ''
+
+ def __repr__(self):
+ return ""
+
+ def __iter__(self):
+ for node in self.nodelist_true:
+ yield node
+ if self.nodelist_false:
+ for node in self.nodelist_false:
+ yield node
+
+ def get_nodes_by_type(self, nodetype):
+ nodes = []
+ if isinstance(self, nodetype):
+ nodes.append(self)
+ nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype))
+ if self.nodelist_false:
+ nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype))
+ return nodes
+
+
+@register.tag('if')
+def smart_if(parser, token):
+ """
+ A smarter {% if %} tag for django templates.
+
+ While retaining current Django functionality, it also handles equality,
+ greater than and less than operators. Some common case examples::
+
+ {% if articles|length >= 5 %}...{% endif %}
+ {% if "ifnotequal tag" != "beautiful" %}...{% endif %}
+
+ Arguments and operators _must_ have a space between them, so
+ ``{% if 1>2 %}`` is not a valid smart if tag.
+
+ All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``),
+ ``!=``, ``>``, ``>=``, ``<`` and ``<=``.
+ """
+ bits = token.split_contents()[1:]
+ var = TemplateIfParser(parser, bits).parse()
+ nodelist_true = parser.parse(('else', 'endif'))
+ token = parser.next_token()
+ if token.contents == 'else':
+ nodelist_false = parser.parse(('endif',))
+ parser.delete_first_token()
+ else:
+ nodelist_false = None
+ return SmartIfNode(var, nodelist_true, nodelist_false)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/forum/urls.py b/forum/urls.py
new file mode 100644
index 00000000..a08fe716
--- /dev/null
+++ b/forum/urls.py
@@ -0,0 +1,72 @@
+import os.path
+from django.conf.urls.defaults import *
+from django.contrib import admin
+from forum import views as app
+from forum.feed import RssLastestQuestionsFeed
+from django.utils.translation import ugettext as _
+
+admin.autodiscover()
+feeds = {
+ 'rss': RssLastestQuestionsFeed
+}
+
+APP_PATH = os.path.dirname(os.path.dirname(__file__))
+urlpatterns = patterns('',
+ url(r'^$', app.index, name='index'),
+ (r'^favicon\.ico$', 'django.views.generic.simple.redirect_to', {'url': '/content/images/favicon.ico'}),
+ (r'^favicon\.gif$', 'django.views.generic.simple.redirect_to', {'url': '/content/images/favicon.gif'}),
+ (r'^content/(?P.*)$', 'django.views.static.serve',
+ {'document_root': os.path.join(APP_PATH, 'templates/content').replace('\\','/')}
+ ),
+ (r'^%s(?P.*)$' % _('upfiles/'), 'django.views.static.serve',
+ {'document_root': os.path.join(APP_PATH, 'templates/upfiles').replace('\\','/')}
+ ),
+ (r'^%s/$' % _('signin/'), 'django_authopenid.views.signin'),
+ url(r'^%s$' % _('about/'), app.about, name='about'),
+ url(r'^%s$' % _('faq/'), app.faq, name='faq'),
+ url(r'^%s$' % _('privacy/'), app.privacy, name='privacy'),
+ url(r'^%s$' % _('logout/'), app.logout, name='logout'),
+ url(r'^%s(?P\d+)/%s$' % (_('answers/'), _('comments/')), app.answer_comments, name='answer_comments'),
+ url(r'^%s(?P\d+)/%s$' % (_('answers/'), _('edit/')), app.edit_answer, name='edit_answer'),
+ url(r'^%s(?P\d+)/%s$' % (_('answers/'), _('revisions/')), app.answer_revisions, name='answer_revisions'),
+ url(r'^%s$' % _('questions/'), app.questions, name='questions'),
+ url(r'^%s%s$' % (_('questions/'), _('ask/')), app.ask, name='ask'),
+ url(r'^%s%s$' % (_('questions/'), _('unanswered/')), app.unanswered, name='unanswered'),
+ url(r'^%s(?P\d+)/%s$' % (_('questions/'), _('edit/')), app.edit_question, name='edit_question'),
+ url(r'^%s(?P\d+)/%s$' % (_('questions/'), _('close/')), app.close, name='close'),
+ url(r'^%s(?P\d+)/%s$' % (_('questions/'), _('reopen/')), app.reopen, name='reopen'),
+ url(r'^%s(?P\d+)/%s$' % (_('questions/'), _('answer/')), app.answer, name='answer'),
+ url(r'^%s(?P\d+)/%s$' % (_('questions/'), _('vote/')), app.vote, name='vote'),
+ url(r'^%s(?P\d+)/%s$' % (_('questions/'), _('revisions/')), app.question_revisions, name='question_revisions'),
+ url(r'^%s(?P\d+)/%s$' % (_('questions/'), _('comments/')), app.question_comments, name='question_comments'),
+
+ url(r'^%s(?P\d+)/%s(?P\d+)/%s$' % (_('questions/'), _('comments/'),_('delete/')), \
+ app.delete_comment, kwargs={'commented_object_type':'question'},\
+ name='delete_question_comment'),
+
+ url(r'^%s(?P\d+)/%s(?P\d+)/%s$' % (_('answers/'), _('comments/'),_('delete/')), \
+ app.delete_comment, kwargs={'commented_object_type':'answer'}, \
+ name='delete_answer_comment'), \
+ #place general question item in the end of other operations
+ url(r'^%s(?P\d+)//*' % _('question/'), app.question, name='question'),
+ url(r'^%s$' % _('tags/'), app.tags, name='tags'),
+ url(r'^%s(?P[^/]+)/$' % _('tags/'), app.tag),
+ url(r'^%s$' % _('users/'),app.users, name='users'),
+ url(r'^%s(?P\d+)/$' % _('moderate-user/'), app.moderate_user, name='moderate_user'),
+ url(r'^%s(?P\d+)/%s$' % (_('users/'), _('edit/')), app.edit_user, name='edit_user'),
+ url(r'^%s(?P\d+)//*' % _('users/'), app.user, name='user'),
+ url(r'^%s$' % _('badges/'),app.badges, name='badges'),
+ url(r'^%s(?P\d+)//*' % _('badges/'), app.badge, name='badge'),
+ url(r'^%s%s$' % (_('messages/'), _('markread/')),app.read_message, name='read_message'),
+ # (r'^admin/doc/' % _('admin/doc'), include('django.contrib.admindocs.urls')),
+ (r'^%s(.*)' % _('nimda/'), admin.site.root),
+ url(r'^feeds/(?P.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),
+ (r'^%s$' % _('upload/'), app.upload),
+ url(r'^%s$' % _('books/'), app.books, name='books'),
+ url(r'^%s%s(?P[^/]+)/$' % (_('books/'), _('ask/')), app.ask_book, name='ask_book'),
+ url(r'^%s(?P[^/]+)/$' % _('books/'), app.book, name='book'),
+ url(r'^%s$' % _('search/'), app.search, name='search'),
+ url(r'^%s$' % _('feedback/'), app.feedback, name='feedback'),
+ (r'^%s' % _('account/'), include('django_authopenid.urls')),
+ (r'^i18n/', include('django.conf.urls.i18n')),
+)
diff --git a/forum/user.py b/forum/user.py
index 41811db9..40bf6a89 100644
--- a/forum/user.py
+++ b/forum/user.py
@@ -64,11 +64,11 @@ USER_TEMPLATE_VIEWS = (
data_size = 50
),
UserView(
- id = 'preferences',
- tab_title = _('preferences'),
- tab_description = _('user preference settings'),
- page_title = _('profile - user preferences'),
- view_name = 'user_preferences',
- template_file = 'user_preferences.html'
+ id = 'email_subscriptions',
+ tab_title = _('email subscriptions'),
+ tab_description = _('email subscription settings'),
+ page_title = _('profile - email subscriptions'),
+ view_name = 'user_email_subscriptions',
+ template_file = 'user_email_subscriptions.html'
)
)
diff --git a/forum/views.py b/forum/views.py
index d663a4cb..e4ccaa16 100644
--- a/forum/views.py
+++ b/forum/views.py
@@ -7,16 +7,18 @@ from django.conf import settings
from django.core.files.storage import default_storage
from django.shortcuts import render_to_response, get_object_or_404
from django.contrib.auth.decorators import login_required
-from django.http import HttpResponseRedirect, HttpResponse,Http404
+from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
from django.core.paginator import Paginator, EmptyPage, InvalidPage
-from django.template import RequestContext
+from django.template import RequestContext, loader
from django.utils.html import *
from django.utils import simplejson
from django.core import serializers
+from django.core.mail import mail_admins
from django.db import transaction
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext as _
from django.template.defaultfilters import slugify
+from django.core.exceptions import PermissionDenied
from utils.html import sanitize_html
from markdown2 import Markdown
@@ -28,6 +30,7 @@ from forum.auth import *
from forum.const import *
from forum.user import *
from forum import auth
+from django_authopenid.util import get_next_url
# used in index page
INDEX_PAGE_SIZE = 20
@@ -63,24 +66,28 @@ def _get_tags_cache_json():
tags = simplejson.dumps(tags_list)
return tags
+def _get_and_remember_questions_sort_method(request, view_dic, default):
+ if default not in view_dic:
+ raise Exception('default value must be in view_dic')
+
+ q_sort_method = request.REQUEST.get('sort', None)
+ if q_sort_method == None:
+ q_sort_method = request.session.get('questions_sort_method', default)
+
+ if q_sort_method not in view_dic:
+ q_sort_method = default
+ request.session['questions_sort_method'] = q_sort_method
+ return q_sort_method, view_dic[q_sort_method]
+
def index(request):
- view_id = request.GET.get('sort', None)
view_dic = {
"latest":"-last_activity_at",
"hottest":"-answer_count",
"mostvoted":"-score",
- "trans": "-last_activity_at"
}
- try:
- orderby = view_dic[view_id]
- except KeyError:
- view_id = "latest"
- orderby = "-last_activity_at"
- # group questions by author_id of 28,29
- if view_id == 'trans':
- questions = Question.objects.get_translation_questions(orderby, INDEX_PAGE_SIZE)
- else:
- questions = Question.objects.get_questions_by_pagesize(orderby, INDEX_PAGE_SIZE)
+ view_id, orderby = _get_and_remember_questions_sort_method(request, view_dic, 'latest')
+
+ questions = Question.objects.get_questions_by_pagesize(orderby, INDEX_PAGE_SIZE)
# RISK - inner join queries
questions = questions.select_related()
tags = Tag.objects.get_valid_tags(INDEX_TAGS_SIZE)
@@ -98,7 +105,34 @@ def about(request):
return render_to_response('about.html', context_instance=RequestContext(request))
def faq(request):
- return render_to_response('faq.html', context_instance=RequestContext(request))
+ data = {
+ 'gravatar_faq_url': reverse('faq') + '#gravatar',
+ 'send_email_key_url': reverse('send_email_key'),
+ 'ask_question_url': reverse('ask'),
+ }
+ return render_to_response('faq.html', data, context_instance=RequestContext(request))
+
+def feedback(request):
+ data = {}
+ form = None
+ if request.method == "POST":
+ form = FeedbackForm(request.POST)
+ if form.is_valid():
+ if not request.user.is_authenticated:
+ data['email'] = form.cleaned_data.get('email',None)
+ data['message'] = form.cleaned_data['message']
+ data['name'] = form.cleaned_data.get('name',None)
+ message = render_to_response('feedback_email.txt',data,context_instance=RequestContext(request))
+ mail_admins(_('Q&A forum feedback'), message)
+ msg = _('Thanks for the feedback!')
+ request.user.message_set.create(message=msg)
+ return HttpResponseRedirect(get_next_url(request))
+ else:
+ form = FeedbackForm(initial={'next':get_next_url(request)})
+
+ data['form'] = form
+ return render_to_response('feedback.html', data, context_instance=RequestContext(request))
+feedback.CANCEL_MESSAGE=_('We look forward to hearing your feedback! Please, give it next time :)')
def privacy(request):
return render_to_response('privacy.html', context_instance=RequestContext(request))
@@ -122,13 +156,8 @@ def questions(request, tagname=None, unanswered=False):
except ValueError:
page = 1
- view_id = request.GET.get('sort', None)
view_dic = {"latest":"-added_at", "active":"-last_activity_at", "hottest":"-answer_count", "mostvoted":"-score" }
- try:
- orderby = view_dic[view_id]
- except KeyError:
- view_id = "latest"
- orderby = "-added_at"
+ view_id, orderby = _get_and_remember_questions_sort_method(request,view_dic,'latest')
# check if request is from tagged questions
if tagname is not None:
@@ -208,16 +237,12 @@ def create_new_answer( question=None, author=None,\
#set notification/delete
if email_notify:
- try:
- EmailFeed.objects.get(feed_id = question.id, subscriber_id = author.id, feed_content_type=question_type)
- except EmailFeed.DoesNotExist:
- feed = EmailFeed(content = question, subscriber = author)
- feed.save()
+ if author not in question.followed_by.all():
+ question.followed_by.add(author)
else:
#not sure if this is necessary. ajax should take care of this...
try:
- feed = Email.objects.get(feed_id = question.id, subscriber_id = author.id, feed_content_type=question_type)
- feed.delete()
+ question.followed_by.remove(author)
except:
pass
@@ -267,7 +292,7 @@ def ask(request):
if form.is_valid():
added_at = datetime.datetime.now()
- title = strip_tags(form.cleaned_data['title'])
+ title = strip_tags(form.cleaned_data['title'].strip())
wiki = form.cleaned_data['wiki']
tagnames = form.cleaned_data['tags'].strip()
text = form.cleaned_data['text']
@@ -302,7 +327,7 @@ def ask(request):
ip_addr = request.META['REMOTE_ADDR'],
)
question.save()
- return HttpResponseRedirect('/%s%s%s' % ( _('account/'),_('signin/'),_('newquestion/')))
+ return HttpResponseRedirect(reverse('user_signin_new_question'))
else:
form = AskForm()
@@ -310,6 +335,7 @@ def ask(request):
return render_to_response('ask.html', {
'form' : form,
'tags' : tags,
+ 'email_validation_faq_url':reverse('faq') + '#validate',
}, context_instance=RequestContext(request))
def question(request, id):
@@ -317,13 +343,26 @@ def question(request, id):
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
- view_id = request.GET.get('sort', 'votes')
+
+ view_id = request.GET.get('sort', None)
view_dic = {"latest":"-added_at", "oldest":"added_at", "votes":"-score" }
try:
orderby = view_dic[view_id]
except KeyError:
- view_id = "votes"
- orderby = "-score"
+ qsm = request.session.get('questions_sort_method',None)
+ if qsm in ('mostvoted','latest'):
+ logging.debug('loaded from session ' + qsm)
+ if qsm == 'mostvoted':
+ view_id = 'votes'
+ orderby = '-score'
+ else:
+ view_id = 'latest'
+ orderby = '-added_at'
+ else:
+ view_id = "votes"
+ orderby = "-score"
+
+ logging.debug('view_id=' + str(view_id))
question = get_object_or_404(Question, id=id)
if question.deleted and not can_view_deleted_post(request.user, question):
@@ -349,7 +388,6 @@ def question(request, id):
vote_value = 1
user_answer_votes[answer.id] = vote_value
-
if answers is not None:
answers = answers.order_by("-accepted", orderby)
@@ -363,8 +401,38 @@ def question(request, id):
objects_list = Paginator(filtered_answers, ANSWERS_PAGE_SIZE)
page_objects = objects_list.page(page)
- # update view count
- Question.objects.update_view_count(question)
+
+ #todo: merge view counts per user and per session
+ #1) view count per session
+ update_view_count = False
+ if 'question_view_times' not in request.session:
+ request.session['question_view_times'] = {}
+
+ last_seen = request.session['question_view_times'].get(question.id,None)
+ updated_when, updated_who = question.get_last_update_info()
+
+ if updated_who != request.user:
+ if last_seen:
+ if last_seen < updated_when:
+ update_view_count = True
+ else:
+ update_view_count = True
+
+ request.session['question_view_times'][question.id] = datetime.datetime.now()
+
+ if update_view_count:
+ question.view_count += 1
+ question.save()
+
+ #2) question view count per user
+ if request.user.is_authenticated():
+ try:
+ question_view = QuestionView.objects.get(who=request.user, question=question)
+ except QuestionView.DoesNotExist:
+ question_view = QuestionView(who=request.user, question=question)
+ question_view.when = datetime.datetime.now()
+ question_view.save()
+
return render_to_response('question.html', {
"question" : question,
"question_vote" : question_vote,
@@ -623,6 +691,7 @@ QUESTION_REVISION_TEMPLATE = ('
%(title)s
\n'
def question_revisions(request, id):
post = get_object_or_404(Question, id=id)
revisions = list(post.revisions.all())
+ revisions.reverse()
for i, revision in enumerate(revisions):
revision.html = QUESTION_REVISION_TEMPLATE % {
'title': revision.title,
@@ -631,16 +700,15 @@ def question_revisions(request, id):
for tag in revision.tagnames.split(' ')]),
}
if i > 0:
- revisions[i - 1].diff = htmldiff(revision.html,
- revisions[i - 1].html)
+ revisions[i].diff = htmldiff(revisions[i-1].html, revision.html)
else:
- revisions[i - 1].diff = QUESTION_REVISION_TEMPLATE % {
+ revisions[i].diff = QUESTION_REVISION_TEMPLATE % {
'title': revisions[0].title,
'html': sanitize_html(markdowner.convert(revisions[0].text)),
'tags': ' '.join(['%s' % tag
for tag in revisions[0].tagnames.split(' ')]),
}
- revisions[i - 1].summary = None
+ revisions[i].summary = _('initial version')
return render_to_response('revisions_question.html', {
'post': post,
'revisions': revisions,
@@ -650,16 +718,16 @@ ANSWER_REVISION_TEMPLATE = ('
%(html)s
')
def answer_revisions(request, id):
post = get_object_or_404(Answer, id=id)
revisions = list(post.revisions.all())
+ revisions.reverse()
for i, revision in enumerate(revisions):
revision.html = ANSWER_REVISION_TEMPLATE % {
'html': sanitize_html(markdowner.convert(revision.text))
}
if i > 0:
- revisions[i - 1].diff = htmldiff(revision.html,
- revisions[i - 1].html)
+ revisions[i].diff = htmldiff(revisions[i-1].html, revision.html)
else:
- revisions[i - 1].diff = revisions[i-1].text
- revisions[i - 1].summary = None
+ revisions[i].diff = revisions[i].text
+ revisions[i].summary = _('initial version')
return render_to_response('revisions_answer.html', {
'post': post,
'revisions': revisions,
@@ -696,8 +764,7 @@ def answer(request, id):
ip_addr = request.META['REMOTE_ADDR'],
)
anon.save()
- return HttpResponseRedirect('/%s%s%s' % ( _('account/'),
- _('signin/'),_('newquestion/')))
+ return HttpResponseRedirect(reverse('user_signin_new_answer'))
return HttpResponseRedirect(question.get_absolute_url())
@@ -712,7 +779,7 @@ def tags(request):
if request.method == "GET":
stag = request.GET.get("q", "").strip()
- if stag is not None:
+ if stag != '':
objects_list = Paginator(Tag.objects.filter(deleted=False).exclude(used_count=0).extra(where=['name like %s'], params=['%' + stag + '%']), DEFAULT_PAGE_SIZE)
else:
if sortby == "name":
@@ -738,7 +805,7 @@ def tags(request):
'has_next': tags.has_next(),
'previous': tags.previous_page_number(),
'next': tags.next_page_number(),
- 'base_url' : '/%s?sort=%s&' % (_('tags/'), sortby)
+ 'base_url' : reverse('tags') + '?sort=%s&' % sortby
}
}, context_instance=RequestContext(request))
@@ -930,7 +997,8 @@ def vote(request, id):
if not can_delete_post(request.user, post):
response_data['allowed'] = -2
- elif post.deleted:
+ elif post.deleted == True:
+ logging.debug('debug restoring post in view')
onDeleteCanceled(post, request.user)
response_data['status'] = 1
else:
@@ -939,13 +1007,19 @@ def vote(request, id):
elif vote_type == '11':#subscribe q updates
user = request.user
if user.is_authenticated():
- try:
- EmailFeed.objects.get(feed_id=question.id,subscriber_id=user.id,feed_content_type=question_type)
- except EmailFeed.DoesNotExist:
- feed = EmailFeed(subscriber=user,content=question)
- feed.save()
+ if user not in question.followed_by.all():
+ question.followed_by.add(user)
if settings.EMAIL_VALIDATION == 'on' and user.email_isvalid == False:
- response_data['message'] = _('subscription saved, %(email)s needs validation') % {'email':user.email}
+ response_data['message'] = \
+ _('subscription saved, %(email)s needs validation, see %(details_url)s') \
+ % {'email':user.email,'details_url':reverse('faq') + '#validate'}
+ feed_setting = EmailFeedSetting.objects.get(subscriber=user,feed_type='q_sel')
+ if feed_setting.frequency == 'n':
+ feed_setting.frequency = 'd'
+ feed_setting.save()
+ if 'message' in response_data:
+ response_data['message'] += ' '
+ response_data['message'] = _('email update frequency has been set to daily')
#response_data['status'] = 1
#responst_data['allowed'] = 1
else:
@@ -955,12 +1029,8 @@ def vote(request, id):
elif vote_type == '12':#unsubscribe q updates
user = request.user
if user.is_authenticated():
- try:
- feed = EmailFeed.objects.get(feed_id=question.id,subscriber_id=user.id)
- feed.delete()
- except EmailFeed.DoesNotExist:
- pass
-
+ if user in question.followed_by.all():
+ question.followed_by.remove(user)
else:
response_data['success'] = 0
response_data['message'] = u'Request mode is not supported. Please try again.'
@@ -991,11 +1061,11 @@ def users(request):
# default
else:
objects_list = Paginator(User.objects.all().order_by('-reputation'), USERS_PAGE_SIZE)
- base_url = '/%s?sort=%s&' % (_('users/'), sortby)
+ base_url = reverse('users') + '?sort=%s&' % sortby
else:
sortby = "reputation"
objects_list = Paginator(User.objects.extra(where=['username like %s'], params=['%' + suser + '%']).order_by('-reputation'), USERS_PAGE_SIZE)
- base_url = '/%s?name=%s&sort=%s&' % (_('users/'), suser, sortby)
+ base_url = reverse('users') + '?name=%s&sort=%s&' % (suser, sortby)
try:
users = objects_list.page(page)
@@ -1027,6 +1097,26 @@ def user(request, id):
func = getattr(views, user_view.view_name)
return func(request, id, user_view)
+@login_required
+def moderate_user(request, id):
+ """ajax handler of user moderation
+ """
+ if not auth.can_moderate_users(request.user) or request.method != 'POST':
+ raise Http404
+ if not request.is_ajax():
+ return HttpResponseForbidden(mimetype="application/json")
+
+ user = get_object_or_404(User, id=id)
+ form = ModerateUserForm(request.POST, instance=user)
+
+ if form.is_valid():
+ form.save()
+ logging.debug('data saved')
+ response = HttpResponse(simplejson.dumps(''), mimetype="application/json")
+ else:
+ response = HttpResponseForbidden(mimetype="application/json")
+ return response
+
@login_required
def edit_user(request, id):
user = get_object_or_404(User, id=id)
@@ -1058,6 +1148,7 @@ def edit_user(request, id):
form = EditUserForm(user)
return render_to_response('user_edit.html', {
'form' : form,
+ 'gravatar_faq_url' : reverse('faq') + '#gravatar',
}, context_instance=RequestContext(request))
def user_stats(request, user_id, user_view):
@@ -1111,7 +1202,7 @@ def user_stats(request, user_id, user_view):
'comment_count' : 'answer.comment_count'
},
tables=['question', 'answer'],
- where=['answer.deleted=0 AND answer.author_id=%s AND answer.question_id=question.id'],
+ where=['answer.deleted=0 AND question.deleted=0 AND answer.author_id=%s AND answer.question_id=question.id'],
params=[user_id],
order_by=['-vote_count', '-answer_id'],
select_params=[user_id]
@@ -1152,7 +1243,13 @@ def user_stats(request, user_id, user_view):
from django.db.models import Count
awards = awards.annotate(count = Count('badge__id'))
+ if auth.can_moderate_users(request.user):
+ moderate_user_form = ModerateUserForm(instance=user)
+ else:
+ moderate_user_form = None
+
return render_to_response(user_view.template_file,{
+ 'moderate_user_form': moderate_user_form,
"tab_name" : user_view.id,
"tab_description" : user_view.tab_description,
"page_title" : user_view.page_title,
@@ -1184,10 +1281,9 @@ def user_recent(request, user_id, user_view):
self.title = title
self.summary = summary
slug_title = slugify(title)
+ self.title_link = reverse('question', kwargs={'id':question_id}) + u'%s' % slug_title
if int(answer_id) > 0:
- self.title_link = u'/%s%s/%s#%s' %(_('questions/'),question_id, slug_title, answer_id)
- else:
- self.title_link = u'/%s%s/%s' %(_('questions/'),question_id, slug_title)
+ self.title_link += '#%s' % answer_id
class AwardEvent:
def __init__(self, time, type, id):
@@ -1207,7 +1303,7 @@ def user_recent(request, user_id, user_view):
},
tables=['activity', 'question'],
where=['activity.content_type_id = %s AND activity.object_id = ' +
- 'question.id AND activity.user_id = %s AND activity.activity_type = %s'],
+ 'question.id AND question.deleted=0 AND activity.user_id = %s AND activity.activity_type = %s'],
params=[question_type_id, user_id, TYPE_ACTIVITY_ASK_QUESTION],
order_by=['-activity.active_at']
).values(
@@ -1232,7 +1328,8 @@ def user_recent(request, user_id, user_view):
},
tables=['activity', 'answer', 'question'],
where=['activity.content_type_id = %s AND activity.object_id = answer.id AND ' +
- 'answer.question_id=question.id AND activity.user_id=%s AND activity.activity_type=%s'],
+ 'answer.question_id=question.id AND answer.deleted=0 AND activity.user_id=%s AND '+
+ 'activity.activity_type=%s AND question.deleted=0'],
params=[answer_type_id, user_id, TYPE_ACTIVITY_ANSWER],
order_by=['-activity.active_at']
).values(
@@ -1259,7 +1356,8 @@ def user_recent(request, user_id, user_view):
where=['activity.content_type_id = %s AND activity.object_id = comment.id AND '+
'activity.user_id = comment.user_id AND comment.object_id=question.id AND '+
- 'comment.content_type_id=%s AND activity.user_id = %s AND activity.activity_type=%s'],
+ 'comment.content_type_id=%s AND activity.user_id = %s AND activity.activity_type=%s AND ' +
+ 'question.deleted=0'],
params=[comment_type_id, question_type_id, user_id, TYPE_ACTIVITY_COMMENT_QUESTION],
order_by=['-comment.added_at']
).values(
@@ -1288,7 +1386,8 @@ def user_recent(request, user_id, user_view):
where=['activity.content_type_id = %s AND activity.object_id = comment.id AND '+
'activity.user_id = comment.user_id AND comment.object_id=answer.id AND '+
'comment.content_type_id=%s AND question.id = answer.question_id AND '+
- 'activity.user_id = %s AND activity.activity_type=%s'],
+ 'activity.user_id = %s AND activity.activity_type=%s AND '+
+ 'answer.deleted=0 AND question.deleted=0'],
params=[comment_type_id, answer_type_id, user_id, TYPE_ACTIVITY_COMMENT_ANSWER],
order_by=['-comment.added_at']
).values(
@@ -1313,8 +1412,9 @@ def user_recent(request, user_id, user_view):
'activity_type' : 'activity.activity_type',
'summary' : 'question_revision.summary'
},
- tables=['activity', 'question_revision'],
+ tables=['activity', 'question_revision', 'question'],
where=['activity.content_type_id = %s AND activity.object_id = question_revision.id AND '+
+ 'question_revision.id=question.id AND question.deleted=0 AND '+
'activity.user_id = question_revision.author_id AND activity.user_id = %s AND '+
'activity.activity_type=%s'],
params=[question_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_QUESTION],
@@ -1347,6 +1447,7 @@ def user_recent(request, user_id, user_view):
where=['activity.content_type_id = %s AND activity.object_id = answer_revision.id AND '+
'activity.user_id = answer_revision.author_id AND activity.user_id = %s AND '+
'answer_revision.answer_id=answer.id AND answer.question_id = question.id AND '+
+ 'question.deleted=0 AND answer.deleted=0 AND '+
'activity.activity_type=%s'],
params=[answer_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_ANSWER],
order_by=['-activity.active_at']
@@ -1375,6 +1476,7 @@ def user_recent(request, user_id, user_view):
tables=['activity', 'answer', 'question'],
where=['activity.content_type_id = %s AND activity.object_id = answer.id AND '+
'activity.user_id = question.author_id AND activity.user_id = %s AND '+
+ 'answer.deleted=0 AND question.deleted=0 AND '+
'answer.question_id=question.id AND activity.activity_type=%s'],
params=[answer_type_id, user_id, TYPE_ACTIVITY_MARK_ANSWER],
order_by=['-activity.active_at']
@@ -1427,9 +1529,9 @@ def user_responses(request, user_id, user_view):
def __init__(self, type, title, question_id, answer_id, time, username, user_id, content):
self.type = type
self.title = title
- self.titlelink = u'/%s%s/%s#%s' % (_('questions/'), question_id, title, answer_id)
+ self.titlelink = reverse('questions') + u'%s/%s#%s' % (question_id, title, answer_id)
self.time = time
- self.userlink = u'/%s%s/%s/' % (_('users/'), user_id, username)
+ self.userlink = reverse('users') + u'%s/%s/' % (user_id, username)
self.username = username
self.content = u'%s ...' % strip_tags(content)[:300]
@@ -1715,86 +1817,110 @@ def user_favorites(request, user_id, user_view):
}, context_instance=RequestContext(request))
-def user_preferences(request, user_id, user_view):
+def user_email_subscriptions(request, user_id, user_view):
user = get_object_or_404(User, id=user_id)
+ if request.method == 'POST':
+ form = EditUserEmailFeedsForm(request.POST)
+ if form.is_valid():
+ if 'save' in request.POST:
+ saved = form.save(user)
+ if saved:
+ action_status = _('changes saved')
+ elif 'stop_email' in request.POST:
+ saved = form.reset().save(user)
+ initial_values = EditUserEmailFeedsForm.NO_EMAIL_INITIAL
+ form = EditUserEmailFeedsForm(initial=initial_values)
+ if saved:
+ action_status = _('email updates canceled')
+ if not saved:
+ action_status = None
+ else:
+ form = EditUserEmailFeedsForm()
+ form.set_initial_values(user)
+ action_status = None
return render_to_response(user_view.template_file,{
- "tab_name" : user_view.id,
- "tab_description" : user_view.tab_description,
- "page_title" : user_view.page_title,
- "view_user" : user,
+ 'tab_name':user_view.id,
+ 'tab_description':user_view.tab_description,
+ 'page_title':user_view.page_title,
+ 'view_user':user,
+ 'email_feeds_form':form,
+ 'action_status':action_status,
}, context_instance=RequestContext(request))
def question_comments(request, id):
question = get_object_or_404(Question, id=id)
user = request.user
- return __comments(request, question, 'question', user)
+ return __comments(request, question, 'question')
def answer_comments(request, id):
answer = get_object_or_404(Answer, id=id)
user = request.user
- return __comments(request, answer, 'answer', user)
+ return __comments(request, answer, 'answer')
-def __comments(request, obj, type, user):
+def __comments(request, obj, type):
# only support get comments by ajax now
+ user = request.user
if request.is_ajax():
if request.method == "GET":
- return __generate_comments_json(obj, type, user)
+ response = __generate_comments_json(obj, type, user)
elif request.method == "POST":
- comment_data = request.POST.get('comment')
- comment = Comment(content_object=obj, comment=comment_data, user=request.user)
- comment.save()
- obj.comment_count = obj.comment_count + 1
- obj.save()
- return __generate_comments_json(obj, type, user)
+ if auth.can_add_comments(user,obj):
+ comment_data = request.POST.get('comment')
+ comment = Comment(content_object=obj, comment=comment_data, user=request.user)
+ comment.save()
+ obj.comment_count = obj.comment_count + 1
+ obj.save()
+ response = __generate_comments_json(obj, type, user)
+ else:
+ response = HttpResponseForbidden(mimetype="application/json")
+ return response
def __generate_comments_json(obj, type, user):
- comments = obj.comments.all().order_by('-id')
+ comments = obj.comments.all().order_by('id')
# {"Id":6,"PostId":38589,"CreationDate":"an hour ago","Text":"hello there!","UserDisplayName":"Jarrod Dixon","UserUrl":"/users/3/jarrod-dixon","DeleteUrl":null}
json_comments = []
+ from forum.templatetags.extra_tags import diff_date
for comment in comments:
comment_user = comment.user
delete_url = ""
if user != None and auth.can_delete_comment(user, comment):
#/posts/392845/comments/219852/delete
- delete_url = "/" + type + "s/%s/comments/%s/delete/" % (obj.id, comment.id)
+ #todo translate this url
+ delete_url = reverse(index) + type + "s/%s/comments/%s/delete/" % (obj.id, comment.id)
json_comments.append({"id" : comment.id,
"object_id" : obj.id,
- "add_date" : comment.added_at.strftime('%Y-%m-%d'),
+ "comment_age" : diff_date(comment.added_at),
"text" : comment.comment,
"user_display_name" : comment_user.username,
- "user_url" : "/%s%s/%s" % (_('users/'), comment_user.id, comment_user.username),
+ "user_url" : comment_user.get_profile_url(),
"delete_url" : delete_url
})
data = simplejson.dumps(json_comments)
return HttpResponse(data, mimetype="application/json")
-def delete_question_comment(request, question_id, comment_id):
- if request.is_ajax():
- question = get_object_or_404(Question, id=question_id)
- comment = get_object_or_404(Comment, id=comment_id)
-
- question.comments.remove(comment)
- question.comment_count = question.comment_count - 1
- question.save()
- user = request.user
- return __generate_comments_json(question, 'question', user)
+def delete_comment(request, object_id='', comment_id='', commented_object_type=None):
+ response = None
+ commented_object = None
+ if commented_object_type == 'question':
+ commented_object = Question
+ elif commented_object_type == 'answer':
+ commented_object = Answer
-def delete_answer_comment(request, answer_id, comment_id):
if request.is_ajax():
- answer = get_object_or_404(Answer, id=answer_id)
comment = get_object_or_404(Comment, id=comment_id)
-
- answer.comments.remove(comment)
- answer.comment_count = answer.comment_count - 1
- answer.save()
- user = request.user
- return __generate_comments_json(answer, 'answer', user)
+ if auth.can_delete_comment(request.user, comment):
+ obj = get_object_or_404(commented_object, id=object_id)
+ obj.comments.remove(comment)
+ obj.comment_count = obj.comment_count - 1
+ obj.save()
+ user = request.user
+ return __generate_comments_json(obj, commented_object_type, user)
+ raise PermissionDenied()
def logout(request):
- url = request.GET.get('next')
return render_to_response('logout.html', {
- 'next' : url,
+ 'next' : get_next_url(request),
}, context_instance=RequestContext(request))
def badges(request):
@@ -1807,6 +1933,7 @@ def badges(request):
return render_to_response('badges.html', {
'badges' : badges,
'mybadges' : my_badges,
+ 'feedback_faq_url' : reverse('feedback'),
}, context_instance=RequestContext(request))
def badge(request, id):
@@ -1882,7 +2009,7 @@ def upload(request):
return HttpResponse(result, mimetype="application/xml")
def books(request):
- return HttpResponseRedirect("/books/mysql-zhaoyang")
+ return HttpResponseRedirect(reverse('books') + '/mysql-zhaoyang')
def book(request, short_name, unanswered=False):
"""
@@ -2007,6 +2134,7 @@ def ask_book(request, short_name):
return render_to_response('ask.html', {
'form' : form,
'tags' : tags,
+ 'email_validation_faq_url': reverse('faq') + '#validate',
}, context_instance=RequestContext(request))
def search(request):
@@ -2022,11 +2150,11 @@ def search(request):
except ValueError:
page = 1
if keywords is None:
- return HttpResponseRedirect('/')
+ return HttpResponseRedirect(reverse(index))
if search_type == 'tag':
- return HttpResponseRedirect('/%s?q=%s&page=%s' % (_('tags/'), keywords.strip(), page))
+ return HttpResponseRedirect(reverse('tags') + '?q=%s&page=%s' % (keywords.strip(), page))
elif search_type == "user":
- return HttpResponseRedirect('/%s?q=%s&page=%s' % (_('users/'), keywords.strip(), page))
+ return HttpResponseRedirect(reverse('users') + '?q=%s&page=%s' % (keywords.strip(), page))
elif search_type == "question":
template_file = "questions.html"
diff --git a/junk.py b/junk.py
new file mode 100644
index 00000000..c6c03d27
--- /dev/null
+++ b/junk.py
@@ -0,0 +1,3 @@
+import os
+
+print os.path.normpath('/haha//haha')
diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo
index cd8de560..502c1075 100644
Binary files a/locale/en/LC_MESSAGES/django.mo and b/locale/en/LC_MESSAGES/django.mo differ
diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po
index b5e5c549..18eb61b1 100644
--- a/locale/en/LC_MESSAGES/django.po
+++ b/locale/en/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-08-19 00:41+0000\n"
+"POT-Creation-Date: 2009-11-10 19:00-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -16,339 +16,315 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: settings.py:12 urls.py:25 forum/views.py:305 forum/views.py:699
-msgid "account/"
-msgstr ""
-
-#: settings.py:12 urls.py:26 django_authopenid/urls.py:9
-#: django_authopenid/urls.py:10 django_authopenid/urls.py:11
-#: django_authopenid/urls.py:13 forum/views.py:305 forum/views.py:700
-#: templates/authopenid/confirm_email.txt:10
-msgid "signin/"
-msgstr ""
-
-#: urls.py:22
-msgid "upfiles/"
-msgstr ""
-
-#: urls.py:27 urls.py:28 urls.py:29 django_authopenid/urls.py:26
-#: django_authopenid/urls.py:27
-msgid "email/"
-msgstr ""
-
-#: urls.py:27
-msgid "change/"
-msgstr ""
-
-#: urls.py:28
-msgid "sendkey/"
-msgstr ""
-
-#: urls.py:29
-msgid "verify/"
-msgstr ""
-
-#: urls.py:30
-msgid "about/"
-msgstr ""
-
-#: urls.py:31
-msgid "faq/"
-msgstr ""
+#: django_authopenid/forms.py:70
+msgid "choose a username"
+msgstr "Choose screen name"
-#: urls.py:32
-msgid "privacy/"
+#: django_authopenid/forms.py:76
+msgid "user name is required"
msgstr ""
-#: urls.py:33
-msgid "logout/"
+#: django_authopenid/forms.py:77
+msgid "sorry, this name is taken, please choose another"
msgstr ""
-#: urls.py:34 urls.py:35 urls.py:36 urls.py:48 forum/models.py:418
-msgid "answers/"
+#: django_authopenid/forms.py:78
+msgid "sorry, this name is not allowed, please choose another"
msgstr ""
-#: urls.py:34 urls.py:46
-msgid "comments/"
+#: django_authopenid/forms.py:79
+msgid "sorry, there is no user with this name"
msgstr ""
-#: urls.py:35 urls.py:40 urls.py:54 templates/user_info.html:34
-msgid "edit/"
+#: django_authopenid/forms.py:80
+msgid "sorry, we have a serious error - user name is taken by several users"
msgstr ""
-#: urls.py:36 urls.py:45
-msgid "revisions/"
+#: django_authopenid/forms.py:81
+msgid "user name can only consist of letters, empty space and underscore"
msgstr ""
-#: urls.py:37 urls.py:38 urls.py:39 urls.py:40 urls.py:41 urls.py:42
-#: urls.py:43 urls.py:44 urls.py:45 urls.py:46 urls.py:47 forum/feed.py:19
-#: forum/models.py:306 forum/views.py:1188 forum/views.py:1190
-#: forum/views.py:1430
-msgid "questions/"
-msgstr ""
+#: django_authopenid/forms.py:116
+msgid "your email address"
+msgstr "Your email (never shared)"
-#: urls.py:38 urls.py:64
-msgid "ask/"
+#: django_authopenid/forms.py:117
+msgid "email address is required"
msgstr ""
-#: urls.py:39
-msgid "unanswered/"
+#: django_authopenid/forms.py:118
+msgid "please enter a valid email address"
msgstr ""
-#: urls.py:41
-msgid "close/"
+#: django_authopenid/forms.py:119
+msgid "this email is already used by someone else, please choose another"
msgstr ""
-#: urls.py:42
-msgid "reopen/"
+#: django_authopenid/forms.py:163 django_authopenid/views.py:117
+msgid "i-names are not supported"
msgstr ""
-#: urls.py:43
-msgid "answer/"
+#: django_authopenid/forms.py:239
+msgid "Please enter valid username and password (both are case-sensitive)."
msgstr ""
-#: urls.py:44
-msgid "vote/"
+#: django_authopenid/forms.py:242 django_authopenid/forms.py:292
+msgid "This account is inactive."
msgstr ""
-#: urls.py:47 urls.py:48 django_authopenid/urls.py:29
-msgid "delete/"
+#: django_authopenid/forms.py:244
+msgid "Login failed."
msgstr ""
-#: urls.py:50
-msgid "question/"
+#: django_authopenid/forms.py:246
+msgid "Please enter username and password"
msgstr ""
-#: urls.py:51 urls.py:52 forum/views.py:741 forum/views.py:2027
-msgid "tags/"
+#: django_authopenid/forms.py:248
+msgid "Please enter your password"
msgstr ""
-#: urls.py:53 urls.py:54 urls.py:55 forum/views.py:994 forum/views.py:998
-#: forum/views.py:1432 forum/views.py:1765 forum/views.py:2029
-msgid "users/"
+#: django_authopenid/forms.py:250
+msgid "Please enter user name"
msgstr ""
-#: urls.py:56 urls.py:57
-msgid "badges/"
+#: django_authopenid/forms.py:288
+msgid ""
+"Please enter a valid username and password. Note that "
+"both fields are case-sensitive."
msgstr ""
-#: urls.py:58
-msgid "messages/"
-msgstr ""
+#: django_authopenid/forms.py:310
+msgid "choose password"
+msgstr "Password"
-#: urls.py:58
-msgid "markread/"
+#: django_authopenid/forms.py:311
+msgid "password is required"
msgstr ""
-#: urls.py:60
-msgid "nimda/"
-msgstr ""
+#: django_authopenid/forms.py:314
+msgid "retype password"
+msgstr "Password (please retype)"
-#: urls.py:62
-msgid "upload/"
+#: django_authopenid/forms.py:315
+msgid "please, retype your password"
msgstr ""
-#: urls.py:63 urls.py:64 urls.py:65
-msgid "books/"
+#: django_authopenid/forms.py:316
+msgid "sorry, entered passwords did not match, please try again"
msgstr ""
-#: urls.py:66
-msgid "search/"
+#: django_authopenid/forms.py:341
+msgid "Current password"
msgstr ""
-#: django_authopenid/forms.py:67 django_authopenid/views.py:102
-msgid "i-names are not supported"
+#: django_authopenid/forms.py:343
+msgid "New password"
msgstr ""
-#: django_authopenid/forms.py:102
-msgid ""
-"Usernames can only contain letters, numbers and "
-"underscores"
+#: django_authopenid/forms.py:345
+msgid "Retype new password"
msgstr ""
-#: django_authopenid/forms.py:109
+#: django_authopenid/forms.py:356
msgid ""
-"This username does not exist in our database. Please "
-"choose another."
+"Old password is incorrect. Please enter the correct "
+"password."
msgstr ""
-#: django_authopenid/forms.py:126 django_authopenid/forms.py:233
-msgid ""
-"Please enter a valid username and password. Note that "
-"both fields are case-sensitive."
+#: django_authopenid/forms.py:368
+msgid "new passwords do not match"
msgstr ""
-#: django_authopenid/forms.py:130 django_authopenid/forms.py:237
-msgid "This account is inactive."
+#: django_authopenid/forms.py:432
+msgid "Your user name (required)"
msgstr ""
-#: django_authopenid/forms.py:158 django_authopenid/forms.py:210
-msgid "invalid user name"
-msgstr "User names can contain letters, underscore and empty space."
-
-#: django_authopenid/forms.py:160
-msgid "sorry, this name can not be used, please try another"
-msgstr ""
+#: django_authopenid/forms.py:447
+msgid "Incorrect username."
+msgstr "sorry, there is no such user name"
-#: django_authopenid/forms.py:162
-msgid "username too short"
+#: django_authopenid/urls.py:9 django_authopenid/urls.py:10
+#: django_authopenid/urls.py:11 django_authopenid/urls.py:13 forum/urls.py:24
+msgid "signin/"
msgstr ""
-#: django_authopenid/forms.py:170 django_authopenid/forms.py:171
-msgid "this name is already in use - please try anoter"
+#: django_authopenid/urls.py:10
+msgid "newquestion/"
msgstr ""
-#: django_authopenid/forms.py:185
-msgid ""
-"This email is already registered in our database. "
-"Please choose another."
+#: django_authopenid/urls.py:11
+msgid "newanswer/"
msgstr ""
-#: django_authopenid/forms.py:216
-msgid ""
-"This username don't exist. Please choose another."
+#: django_authopenid/urls.py:12
+msgid "signout/"
msgstr ""
-#: django_authopenid/forms.py:255
-msgid "choose a username"
+#: django_authopenid/urls.py:13
+msgid "complete/"
msgstr ""
-#: django_authopenid/forms.py:257 templates/authopenid/signup.html:38
-msgid "your email address"
-msgstr ""
+#: django_authopenid/urls.py:15
+msgid "external-login/"
+msgstr "using-nmr-wiki-login-and-password/"
-#: django_authopenid/forms.py:259 templates/authopenid/signup.html:39
-msgid "choose password"
+#: django_authopenid/urls.py:16
+msgid "register/"
msgstr ""
-#: django_authopenid/forms.py:261 templates/authopenid/signup.html:40
-msgid "retype password"
+#: django_authopenid/urls.py:17
+msgid "signup/"
msgstr ""
-#: django_authopenid/forms.py:335
-msgid ""
-"Old password is incorrect. Please enter the correct "
-"password."
+#: django_authopenid/urls.py:19
+msgid "sendpw/"
msgstr ""
-#: django_authopenid/forms.py:347
-msgid "new passwords do not match"
+#: django_authopenid/urls.py:20 django_authopenid/urls.py:24
+msgid "password/"
msgstr ""
-#: django_authopenid/forms.py:442
-msgid "Incorrect username."
+#: django_authopenid/urls.py:20
+msgid "confirm/"
msgstr ""
-#: django_authopenid/urls.py:10 forum/views.py:305 forum/views.py:700
-msgid "newquestion/"
+#: django_authopenid/urls.py:23
+msgid "account_settings"
msgstr ""
-#: django_authopenid/urls.py:11
-msgid "newanswer/"
+#: django_authopenid/urls.py:25 django_authopenid/urls.py:26
+#: django_authopenid/urls.py:27 django_authopenid/urls.py:28
+msgid "email/"
msgstr ""
-#: django_authopenid/urls.py:12
-msgid "signout/"
+#: django_authopenid/urls.py:25
+msgid "validate/"
msgstr ""
-#: django_authopenid/urls.py:13
-msgid "complete/"
+#: django_authopenid/urls.py:26
+msgid "change/"
msgstr ""
-#: django_authopenid/urls.py:15
-msgid "register/"
+#: django_authopenid/urls.py:27
+msgid "sendkey/"
msgstr ""
-#: django_authopenid/urls.py:16
-msgid "signup/"
+#: django_authopenid/urls.py:28
+msgid "verify/"
msgstr ""
-#: django_authopenid/urls.py:18
-msgid "sendpw/"
+#: django_authopenid/urls.py:29
+msgid "openid/"
msgstr ""
-#: django_authopenid/urls.py:27
-msgid "validate/"
+#: django_authopenid/urls.py:30 forum/urls.py:43 forum/urls.py:47
+msgid "delete/"
msgstr ""
-#: django_authopenid/views.py:108
+#: django_authopenid/views.py:123
#, python-format
msgid "OpenID %(openid_url)s is invalid"
msgstr ""
-#: django_authopenid/views.py:418 django_authopenid/views.py:545
-msgid "Welcome"
-msgstr "Verification Email from Q&A forum"
+#: django_authopenid/views.py:531
+msgid "Welcome email subject line"
+msgstr "Welcome to the Q&A forum"
-#: django_authopenid/views.py:508
+#: django_authopenid/views.py:626
msgid "Password changed."
msgstr ""
-#: django_authopenid/views.py:520 django_authopenid/views.py:525
-msgid "your email needs to be validated"
+#: django_authopenid/views.py:638 django_authopenid/views.py:644
+#, python-format
+msgid "your email needs to be validated see %(details_url)s"
msgstr ""
"Your email needs to be validated. Please see details here."
+"id='validate_email_alert' href='%(details_url)s'>here."
+
+#: django_authopenid/views.py:665
+msgid "Email verification subject line"
+msgstr "Verification Email from Q&A forum"
+
+#: django_authopenid/views.py:751
+msgid "your email was not changed"
+msgstr ""
-#: django_authopenid/views.py:682 django_authopenid/views.py:834
+#: django_authopenid/views.py:798 django_authopenid/views.py:950
#, python-format
msgid "No OpenID %s found associated in our database"
msgstr ""
-#: django_authopenid/views.py:686 django_authopenid/views.py:841
+#: django_authopenid/views.py:802 django_authopenid/views.py:957
#, python-format
msgid "The OpenID %s isn't associated to current user logged in"
msgstr ""
-#: django_authopenid/views.py:694
+#: django_authopenid/views.py:810
msgid "Email Changed."
msgstr ""
-#: django_authopenid/views.py:769
+#: django_authopenid/views.py:885
msgid "This OpenID is already associated with another account."
msgstr ""
-#: django_authopenid/views.py:774
+#: django_authopenid/views.py:890
#, python-format
msgid "OpenID %s is now associated with your account."
msgstr ""
-#: django_authopenid/views.py:844
+#: django_authopenid/views.py:960
msgid "Account deleted."
msgstr ""
-#: django_authopenid/views.py:884
+#: django_authopenid/views.py:1003
msgid "Request for new password"
msgstr ""
-#: django_authopenid/views.py:897
-msgid "A new password has been sent to your email address."
+#: django_authopenid/views.py:1016
+msgid "A new password and the activation link were sent to your email address."
msgstr ""
-#: django_authopenid/views.py:927
+#: django_authopenid/views.py:1046
#, python-format
msgid ""
"Could not change password. Confirmation key '%s' is not "
"registered."
msgstr ""
-#: django_authopenid/views.py:936
+#: django_authopenid/views.py:1055
msgid ""
"Can not change password. User don't exist anymore in our "
"database."
msgstr ""
-#: django_authopenid/views.py:945
+#: django_authopenid/views.py:1064
#, python-format
msgid "Password changed for %s. You may now sign in."
msgstr ""
+#: forum/auth.py:484
+msgid "Your question and all of it's answers have been deleted"
+msgstr ""
+
+#: forum/auth.py:486
+msgid "Your question has been deleted"
+msgstr ""
+
+#: forum/auth.py:489
+msgid "The question and all of it's answers have been deleted"
+msgstr ""
+
+#: forum/auth.py:491
+msgid "The question has been deleted"
+msgstr ""
+
#: forum/const.py:8
msgid "duplicate question"
msgstr ""
#: forum/const.py:9
-msgid "question if off-topic or not relevant"
+msgid "question is off-topic or not relevant"
msgstr ""
#: forum/const.py:10
@@ -467,151 +443,336 @@ msgstr ""
msgid "latest questions"
msgstr ""
-#: forum/forms.py:14 templates/answer_edit_tips.html:33
-#: templates/answer_edit_tips.html.py:37 templates/question_edit_tips.html:31
-#: templates/question_edit_tips.html:36
+#: forum/feed.py:19 forum/urls.py:32 forum/urls.py:33 forum/urls.py:34
+#: forum/urls.py:35 forum/urls.py:36 forum/urls.py:37 forum/urls.py:38
+#: forum/urls.py:39 forum/urls.py:40 forum/urls.py:41 forum/urls.py:43
+msgid "questions/"
+msgstr ""
+
+#: forum/forms.py:16 templates/answer_edit_tips.html:35
+#: templates/answer_edit_tips.html.py:39 templates/question_edit_tips.html:32
+#: templates/question_edit_tips.html:37
msgid "title"
msgstr ""
-#: forum/forms.py:15
+#: forum/forms.py:17
msgid "please enter a descriptive title for your question"
msgstr ""
-#: forum/forms.py:20
+#: forum/forms.py:22
msgid "title must be > 10 characters"
msgstr ""
-#: forum/forms.py:29
+#: forum/forms.py:31
msgid "content"
msgstr ""
-#: forum/forms.py:35
+#: forum/forms.py:37
msgid "question content must be > 10 characters"
msgstr ""
-#: forum/forms.py:45 templates/header.html:30 templates/header.html.py:64
+#: forum/forms.py:47 templates/header.html:29 templates/header.html.py:63
msgid "tags"
msgstr ""
-#: forum/forms.py:47
+#: forum/forms.py:49
msgid ""
"Tags are short keywords, with no spaces within. Up to five tags can be used."
msgstr ""
-#: forum/forms.py:54 templates/question_retag.html:38
+#: forum/forms.py:56 templates/question_retag.html:39
msgid "tags are required"
msgstr ""
-#: forum/forms.py:58
+#: forum/forms.py:62
msgid "please use 5 tags or less"
msgstr ""
-#: forum/forms.py:61
+#: forum/forms.py:65
msgid "tags must be shorter than 20 characters"
msgstr ""
-#: forum/forms.py:65
+#: forum/forms.py:69
msgid ""
"please use following characters in tags: letters 'a-z', numbers, and "
"characters '.-_#'"
msgstr ""
-#: forum/forms.py:75 templates/index.html:57 templates/question.html:209
-#: templates/question.html.py:395 templates/questions.html:58
-#: templates/questions.html.py:70 templates/unanswered.html:48
-#: templates/unanswered.html.py:60
+#: forum/forms.py:79 templates/index.html:59 templates/index.html.py:71
+#: templates/post_contributor_info.html:7
+#: templates/question_summary_list_roll.html:26
+#: templates/question_summary_list_roll.html:38 templates/questions.html:59
+#: templates/questions.html.py:71 templates/unanswered.html:51
+#: templates/unanswered.html.py:63
msgid "community wiki"
msgstr ""
-#: forum/forms.py:76
+#: forum/forms.py:80
msgid ""
"if you choose community wiki option, the question and answer do not generate "
"points and name of author will not be shown"
msgstr ""
-#: forum/forms.py:89
+#: forum/forms.py:96
msgid "update summary:"
msgstr ""
-#: forum/forms.py:90
+#: forum/forms.py:97
msgid ""
"enter a brief summary of your revision (e.g. fixed spelling, grammar, "
"improved style, this field is optional)"
msgstr ""
-#: forum/forms.py:175
+#: forum/forms.py:100
+msgid "Automatically accept user's contributions for the email updates"
+msgstr ""
+
+#: forum/forms.py:113
+msgid "Your name:"
+msgstr ""
+
+#: forum/forms.py:114
+msgid "Email (not shared with anyone):"
+msgstr ""
+
+#: forum/forms.py:115
+msgid "Your message:"
+msgstr ""
+
+#: forum/forms.py:197
msgid "this email does not have to be linked to gravatar"
msgstr ""
-#: forum/forms.py:176
+#: forum/forms.py:198
msgid "Real name"
msgstr ""
-#: forum/forms.py:177
+#: forum/forms.py:199
msgid "Website"
msgstr ""
-#: forum/forms.py:178
+#: forum/forms.py:200
msgid "Location"
msgstr ""
-#: forum/forms.py:179
+#: forum/forms.py:201
msgid "Date of birth"
msgstr ""
-#: forum/forms.py:179
+#: forum/forms.py:201
msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
msgstr ""
-#: forum/forms.py:180 templates/authopenid/settings.html:21
+#: forum/forms.py:202 templates/authopenid/settings.html:21
msgid "Profile"
msgstr ""
-#: forum/forms.py:207 forum/forms.py:208
+#: forum/forms.py:229 forum/forms.py:230
msgid "this email has already been registered, please use another one"
msgstr ""
-#: forum/models.py:246
+#: forum/forms.py:234 forum/forms.py:235
+msgid "weekly"
+msgstr ""
+
+#: forum/forms.py:234 forum/forms.py:235
+msgid "no email"
+msgstr ""
+
+#: forum/forms.py:235
+msgid "daily"
+msgstr ""
+
+#: forum/forms.py:250 forum/models.py:46
+msgid "Entire forum"
+msgstr ""
+
+#: forum/forms.py:253
+msgid "Asked by me"
+msgstr ""
+
+#: forum/forms.py:256
+msgid "Answered by me"
+msgstr ""
+
+#: forum/forms.py:259
+msgid "Individually selected"
+msgstr ""
+
+#: forum/models.py:47
+msgid "Questions that I asked"
+msgstr ""
+
+#: forum/models.py:48
+msgid "Questions that I answered"
+msgstr ""
+
+#: forum/models.py:49
+msgid "Individually selected questions"
+msgstr ""
+
+#: forum/models.py:52
+msgid "Weekly"
+msgstr ""
+
+#: forum/models.py:53
+msgid "Daily"
+msgstr ""
+
+#: forum/models.py:54
+msgid "No email"
+msgstr ""
+
+#: forum/models.py:289
#, python-format
msgid "%(author)s modified the question"
msgstr ""
-#: forum/models.py:250
+#: forum/models.py:293
#, python-format
msgid "%(people)s posted %(new_answer_count)s new answers"
msgstr ""
-#: forum/models.py:255
+#: forum/models.py:298
#, python-format
msgid "%(people)s commented the question"
msgstr ""
-#: forum/models.py:260
+#: forum/models.py:303
#, python-format
msgid "%(people)s commented answers"
msgstr ""
-#: forum/models.py:262
+#: forum/models.py:305
#, python-format
msgid "%(people)s commented an answer"
msgstr ""
-#: forum/models.py:306 forum/models.py:418
-msgid "revisions"
-msgstr ""
-
-#: forum/models.py:441 templates/badges.html:51
+#: forum/models.py:493 templates/badges.html:53
msgid "gold"
msgstr ""
-#: forum/models.py:442 templates/badges.html:59
+#: forum/models.py:494 templates/badges.html:61
msgid "silver"
msgstr ""
-#: forum/models.py:443 templates/badges.html:66
+#: forum/models.py:495 templates/badges.html:68
msgid "bronze"
msgstr ""
+#: forum/urls.py:21
+msgid "upfiles/"
+msgstr ""
+
+#: forum/urls.py:25
+msgid "about/"
+msgstr ""
+
+#: forum/urls.py:26
+msgid "faq/"
+msgstr ""
+
+#: forum/urls.py:27
+msgid "privacy/"
+msgstr ""
+
+#: forum/urls.py:28
+msgid "logout/"
+msgstr ""
+
+#: forum/urls.py:29 forum/urls.py:30 forum/urls.py:31 forum/urls.py:47
+msgid "answers/"
+msgstr ""
+
+#: forum/urls.py:29 forum/urls.py:41 forum/urls.py:43 forum/urls.py:47
+msgid "comments/"
+msgstr ""
+
+#: forum/urls.py:30 forum/urls.py:35 forum/urls.py:56
+#: templates/user_info.html:45
+msgid "edit/"
+msgstr ""
+
+#: forum/urls.py:31 forum/urls.py:40
+msgid "revisions/"
+msgstr ""
+
+#: forum/urls.py:33 forum/urls.py:66
+msgid "ask/"
+msgstr ""
+
+#: forum/urls.py:34
+msgid "unanswered/"
+msgstr ""
+
+#: forum/urls.py:36
+msgid "close/"
+msgstr ""
+
+#: forum/urls.py:37
+msgid "reopen/"
+msgstr ""
+
+#: forum/urls.py:38
+msgid "answer/"
+msgstr ""
+
+#: forum/urls.py:39
+msgid "vote/"
+msgstr ""
+
+#: forum/urls.py:51
+msgid "question/"
+msgstr ""
+
+#: forum/urls.py:52 forum/urls.py:53
+msgid "tags/"
+msgstr ""
+
+#: forum/urls.py:54 forum/urls.py:56 forum/urls.py:57
+msgid "users/"
+msgstr ""
+
+#: forum/urls.py:55
+msgid "moderate-user/"
+msgstr ""
+
+#: forum/urls.py:58 forum/urls.py:59
+msgid "badges/"
+msgstr ""
+
+#: forum/urls.py:60
+msgid "messages/"
+msgstr ""
+
+#: forum/urls.py:60
+msgid "markread/"
+msgstr ""
+
+#: forum/urls.py:62
+msgid "nimda/"
+msgstr ""
+
+#: forum/urls.py:64
+msgid "upload/"
+msgstr ""
+
+#: forum/urls.py:65 forum/urls.py:66 forum/urls.py:67
+msgid "books/"
+msgstr ""
+
+#: forum/urls.py:68
+msgid "search/"
+msgstr ""
+
+#: forum/urls.py:69
+msgid "feedback/"
+msgstr ""
+
+#: forum/urls.py:70
+msgid "account/"
+msgstr ""
+
#: forum/user.py:16 templates/user_tabs.html:7
msgid "overview"
msgstr ""
@@ -648,17 +809,17 @@ msgstr ""
msgid "profile - responses"
msgstr ""
-#: forum/user.py:42 templates/user_info.html:23 templates/users.html:26
+#: forum/user.py:42 templates/user_info.html:22 templates/users.html:26
msgid "reputation"
-msgstr ""
+msgstr "karma"
#: forum/user.py:43
msgid "user reputation in the community"
-msgstr ""
+msgstr "user karma"
#: forum/user.py:44
msgid "profile - user reputation"
-msgstr ""
+msgstr "Profile - User's Karma"
#: forum/user.py:50
msgid "favorite questions"
@@ -684,61 +845,130 @@ msgstr ""
msgid "profile - votes"
msgstr ""
-#: forum/user.py:68
-msgid "preferences"
+#: forum/user.py:68 templates/user_tabs.html:28
+msgid "email subscriptions"
msgstr ""
#: forum/user.py:69 templates/user_tabs.html:27
-msgid "user preference settings"
+msgid "email subscription settings"
msgstr ""
#: forum/user.py:70
-msgid "profile - user preferences"
+msgid "profile - email subscriptions"
msgstr ""
-#: forum/views.py:948
+#: forum/views.py:126
+msgid "Q&A forum feedback"
+msgstr ""
+
+#: forum/views.py:127
+msgid "Thanks for the feedback!"
+msgstr ""
+
+#: forum/views.py:135
+msgid "We look forward to hearing your feedback! Please, give it next time :)"
+msgstr ""
+
+#: forum/views.py:1014
#, python-format
-msgid "subscription saved, %(email)s needs validation"
+msgid "subscription saved, %(email)s needs validation, see %(details_url)s"
msgstr ""
"Your subscription is saved, but email address %(email)s needs to be "
-"validated, please see more details here"
+"validated, please see more details here"
-#: forum/views.py:1874
-msgid "uploading images is limited to users with >60 reputation points"
+#: forum/views.py:1022
+msgid "email update frequency has been set to daily"
msgstr ""
-#: forum/views.py:1876
+#: forum/views.py:1826
+msgid "changes saved"
+msgstr ""
+
+#: forum/views.py:1832
+msgid "email updates canceled"
+msgstr ""
+
+#: forum/views.py:1999
+msgid "uploading images is limited to users with >60 reputation points"
+msgstr "sorry, file uploading requires karma >60"
+
+#: forum/views.py:2001
msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
msgstr ""
-#: forum/views.py:1878
+#: forum/views.py:2003
#, python-format
msgid "maximum upload file size is %sK"
msgstr ""
-#: forum/views.py:1880
+#: forum/views.py:2005
#, python-format
msgid ""
"Error uploading file. Please contact the site administrator. Thank you. %s"
msgstr ""
-#: forum/management/commands/send_email_alerts.py:35
-msgid "updates from website"
-msgstr "Q&A forum update"
+#: forum/management/commands/send_email_alerts.py:71
+msgid "email update message subject"
+msgstr "news from Q&A forum"
-#: forum/templatetags/extra_tags.py:143 forum/templatetags/extra_tags.py:172
-#: templates/header.html:35
+#: forum/management/commands/send_email_alerts.py:72
+#, python-format
+msgid "%(name)s, this is an update message header for a question"
+msgid_plural "%(name)s, this is an update message header for %(num)d questions"
+msgstr[0] "
Dear %(name)s,
The following question has been updated on the Q&A forum:"
+msgstr[1] "
Dear %(name)s,
The following %(num)d questions have been updated on the Q&A forum:
"
+
+#: forum/management/commands/send_email_alerts.py:81
+#, python-format
+msgid ""
+"go to %(link)s to change frequency of email updates or %(email)s "
+"administrator"
+msgstr ""
+"
Please remember that you can always adjust frequency of the "
+"email updates or turn them off entirely. If you believe that this message "
+"was sent in an error, please email about it the forum administrator at %(email)"
+"s.
"
+"
Sincerely,
Your friendly Q&A forum server.
"
+
+#: forum/templatetags/extra_tags.py:160 forum/templatetags/extra_tags.py:189
+#: templates/header.html:34
msgid "badges"
msgstr ""
-#: forum/templatetags/extra_tags.py:144 forum/templatetags/extra_tags.py:171
+#: forum/templatetags/extra_tags.py:161 forum/templatetags/extra_tags.py:188
msgid "reputation points"
+msgstr "karma"
+
+#: forum/templatetags/extra_tags.py:244
+msgid "%b %d at %H:%M"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:246
+msgid "%b %d '%y at %H:%M"
+msgstr ""
+
+#: forum/templatetags/extra_tags.py:248
+msgid "2 days ago"
msgstr ""
-#: forum/templatetags/extra_tags.py:225
-msgid " ago"
+#: forum/templatetags/extra_tags.py:250
+msgid "yesterday"
msgstr ""
+#: forum/templatetags/extra_tags.py:252
+#, python-format
+msgid "%(hr)d hour ago"
+msgid_plural "%(hr)d hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: forum/templatetags/extra_tags.py:254
+#, python-format
+msgid "%(min)d min ago"
+msgid_plural "%(min)d mins ago"
+msgstr[0] ""
+msgstr[1] ""
+
#: templates/404.html:24
msgid "Sorry, could not find the page you requested."
msgstr ""
@@ -805,55 +1035,55 @@ msgstr ""
msgid "About"
msgstr ""
-#: templates/answer_edit.html:4 templates/answer_edit.html.py:47
+#: templates/answer_edit.html:5 templates/answer_edit.html.py:48
msgid "Edit answer"
msgstr ""
-#: templates/answer_edit.html:24 templates/answer_edit.html.py:27
-#: templates/ask.html:25 templates/ask.html.py:28 templates/question.html:43
-#: templates/question.html.py:46 templates/question_edit.html:27
+#: templates/answer_edit.html:25 templates/answer_edit.html.py:28
+#: templates/ask.html:26 templates/ask.html.py:29 templates/question.html:45
+#: templates/question.html.py:48 templates/question_edit.html:28
msgid "hide preview"
msgstr ""
-#: templates/answer_edit.html:27 templates/ask.html:28
-#: templates/question.html:46 templates/question_edit.html:27
+#: templates/answer_edit.html:28 templates/ask.html:29
+#: templates/question.html:48 templates/question_edit.html:28
msgid "show preview"
msgstr ""
-#: templates/answer_edit.html:47 templates/question_edit.html:65
-#: templates/question_retag.html:52 templates/revisions_answer.html:36
+#: templates/answer_edit.html:48 templates/question_edit.html:66
+#: templates/question_retag.html:53 templates/revisions_answer.html:36
#: templates/revisions_question.html:36
msgid "back"
msgstr ""
-#: templates/answer_edit.html:52 templates/question_edit.html:70
-#: templates/revisions_answer.html:47 templates/revisions_question.html:47
+#: templates/answer_edit.html:53 templates/question_edit.html:71
+#: templates/revisions_answer.html:50 templates/revisions_question.html:50
msgid "revision"
msgstr ""
-#: templates/answer_edit.html:55 templates/question_edit.html:74
+#: templates/answer_edit.html:56 templates/question_edit.html:75
msgid "select revision"
msgstr ""
-#: templates/answer_edit.html:62 templates/ask.html:94
-#: templates/question.html:467 templates/question_edit.html:91
+#: templates/answer_edit.html:63 templates/ask.html:97
+#: templates/question.html:434 templates/question_edit.html:92
msgid "Toggle the real time Markdown editor preview"
msgstr ""
-#: templates/answer_edit.html:62 templates/ask.html:94
-#: templates/question.html:467 templates/question_edit.html:91
+#: templates/answer_edit.html:63 templates/ask.html:97
+#: templates/question.html:435 templates/question_edit.html:92
msgid "toggle preview"
msgstr ""
-#: templates/answer_edit.html:71 templates/question_edit.html:115
-#: templates/question_retag.html:73
+#: templates/answer_edit.html:72 templates/question_edit.html:118
+#: templates/question_retag.html:74
msgid "Save edit"
msgstr ""
-#: templates/answer_edit.html:72 templates/close.html:29
-#: templates/question_edit.html:116 templates/question_retag.html:74
-#: templates/reopen.html:30 templates/user_edit.html:83
-#: templates/authopenid/changeemail.html:34
+#: templates/answer_edit.html:73 templates/close.html:29
+#: templates/feedback.html:50 templates/question_edit.html:119
+#: templates/question_retag.html:75 templates/reopen.html:30
+#: templates/user_edit.html:83 templates/authopenid/changeemail.html:40
msgid "Cancel"
msgstr ""
@@ -877,80 +1107,82 @@ msgstr ""
msgid "be clear and concise"
msgstr ""
-#: templates/answer_edit_tips.html:19 templates/question_edit_tips.html:16
+#: templates/answer_edit_tips.html:20 templates/question_edit_tips.html:17
msgid "see frequently asked questions"
msgstr ""
-#: templates/answer_edit_tips.html:24 templates/question_edit_tips.html:22
+#: templates/answer_edit_tips.html:26 templates/question_edit_tips.html:23
msgid "Markdown tips"
msgstr "Markdown basics"
-#: templates/answer_edit_tips.html:27 templates/question_edit_tips.html:25
+#: templates/answer_edit_tips.html:29 templates/question_edit_tips.html:26
msgid "*italic* or __italic__"
msgstr ""
-#: templates/answer_edit_tips.html:30 templates/question_edit_tips.html:28
+#: templates/answer_edit_tips.html:32 templates/question_edit_tips.html:29
msgid "**bold** or __bold__"
msgstr ""
-#: templates/answer_edit_tips.html:33 templates/question_edit_tips.html:31
+#: templates/answer_edit_tips.html:35 templates/question_edit_tips.html:32
msgid "link"
msgstr ""
-#: templates/answer_edit_tips.html:33 templates/answer_edit_tips.html.py:37
-#: templates/question_edit_tips.html:31 templates/question_edit_tips.html:36
+#: templates/answer_edit_tips.html:35 templates/answer_edit_tips.html.py:39
+#: templates/question_edit_tips.html:32 templates/question_edit_tips.html:37
msgid "text"
msgstr ""
-#: templates/answer_edit_tips.html:37 templates/question_edit_tips.html:36
+#: templates/answer_edit_tips.html:39 templates/question_edit_tips.html:37
msgid "image"
msgstr ""
-#: templates/answer_edit_tips.html:41 templates/question_edit_tips.html:40
+#: templates/answer_edit_tips.html:43 templates/question_edit_tips.html:41
msgid "numbered list:"
msgstr ""
-#: templates/answer_edit_tips.html:46 templates/question_edit_tips.html:45
+#: templates/answer_edit_tips.html:48 templates/question_edit_tips.html:46
msgid "basic HTML tags are also supported"
msgstr ""
-#: templates/answer_edit_tips.html:49 templates/question_edit_tips.html:48
+#: templates/answer_edit_tips.html:52 templates/question_edit_tips.html:50
msgid "learn more about Markdown"
msgstr ""
-#: templates/ask.html:4 templates/ask.html.py:60
+#: templates/ask.html:5 templates/ask.html.py:61
msgid "Ask a question"
msgstr ""
-#: templates/ask.html:67
+#: templates/ask.html:68
msgid "login to post question info"
msgstr ""
"You are welcome to start submitting your question "
-"anonymously - you are currently not logged in. When you post your "
-"question, you will be redirected to the login/signup page. Your question "
-"will be saved meanwhile and will be posted when you log in. Login/signup "
-"process is very simple. Login takes about 30 seconds, initial signup takes a "
-"minute or less."
+"anonymously. When you submit the post, you will be redirected to the "
+"login/signup page. Your question will be saved in the current session and "
+"will be published after you log in. Login/signup process is very simple. "
+"Login takes about 30 seconds, initial signup takes a minute or less."
-#: templates/ask.html:73
+#: templates/ask.html:74
#, python-format
-msgid "must have valid %(email)s to post"
+msgid ""
+"must have valid %(email)s to post, \n"
+" see %(email_validation_faq_url)s\n"
+" "
msgstr ""
"Looks like your email address, %(email)s has not "
"yet been validated. To post messages you must verify your email, "
-"please see more details here. You can submit "
-"your question now and validate email after that. Your question will saved as "
-"pending meanwhile. "
+"please see more details here."
+" You can submit your question now and validate email after that. Your "
+"question will saved as pending meanwhile. "
-#: templates/ask.html:107
+#: templates/ask.html:112
msgid "(required)"
msgstr ""
-#: templates/ask.html:114
+#: templates/ask.html:119
msgid "Login/signup to post your question"
msgstr "Login/Signup to Post"
-#: templates/ask.html:116
+#: templates/ask.html:121
msgid "Ask your question"
msgstr "Ask Your Question"
@@ -966,7 +1198,7 @@ msgstr ""
msgid "Badges summary"
msgstr ""
-#: templates/badges.html:17 templates/user_stats.html:73
+#: templates/badges.html:17
msgid "Badges"
msgstr ""
@@ -977,38 +1209,41 @@ msgstr ""
"Q&A community will be recognized with the variety of badges."
#: templates/badges.html:22
+#, python-format
msgid ""
-"Below is the list of available badges and number of times each type of badge "
-"has been awarded."
+"Below is the list of available badges and number \n"
+" of times each type of badge has been awarded. Give us feedback at %"
+"(feedback_faq_url)s.\n"
+" "
msgstr ""
"Currently badges differ only by their level: gold, "
"silver and bronze (their meanings are "
"described on the right). In the future there will be many types of badges at "
-"each level. Please give us your feedback"
-"a> - what kinds of badges would you like to see and suggest the "
-"activity for which those badges might be awarded."
+"each level. Please give us your feedback - what kinds of badges would you like to see and "
+"suggest the activity for which those badges might be awarded."
-#: templates/badges.html:48
+#: templates/badges.html:50
msgid "Community badges"
msgstr "Badge levels"
-#: templates/badges.html:54
+#: templates/badges.html:56
msgid "gold badge description"
msgstr ""
"Gold badge is the highest award in this community. To obtain it have to show "
"profound knowledge and ability in addition to your active participation."
-#: templates/badges.html:62
+#: templates/badges.html:64
msgid "silver badge description"
msgstr ""
"Obtaining silver badge requires significant patience. If you have received "
"one, that means you have greatly contributed to this community."
-#: templates/badges.html:65
+#: templates/badges.html:67
msgid "bronze badge: often given as a special honor"
msgstr ""
-#: templates/badges.html:69
+#: templates/badges.html:71
msgid "bronze badge description"
msgstr ""
"If you are an active participant in this community, you will be recognized "
@@ -1080,8 +1315,9 @@ msgstr ""
msgid "number of times"
msgstr ""
-#: templates/book.html:105 templates/index.html:48 templates/questions.html:46
-#: templates/unanswered.html:37 templates/users_questions.html:32
+#: templates/book.html:105 templates/index.html:47
+#: templates/question_summary_list_roll.html:14 templates/questions.html:47
+#: templates/unanswered.html:39 templates/users_questions.html:32
msgid "votes"
msgstr ""
@@ -1089,15 +1325,17 @@ msgstr ""
msgid "the answer has been accepted to be correct"
msgstr ""
-#: templates/book.html:115 templates/index.html:49 templates/questions.html:47
-#: templates/unanswered.html:38 templates/users_questions.html:42
+#: templates/book.html:115 templates/index.html:48
+#: templates/question_summary_list_roll.html:15 templates/questions.html:48
+#: templates/unanswered.html:40 templates/users_questions.html:40
msgid "views"
msgstr ""
-#: templates/book.html:125 templates/index.html:69 templates/question.html:499
-#: templates/questions.html:84 templates/questions.html.py:156
-#: templates/tags.html:49 templates/unanswered.html:75
-#: templates/unanswered.html.py:106 templates/users_questions.html:54
+#: templates/book.html:125 templates/index.html:103
+#: templates/question.html:480 templates/question_summary_list_roll.html:52
+#: templates/questions.html:103 templates/questions.html.py:171
+#: templates/tags.html:49 templates/unanswered.html:95
+#: templates/unanswered.html.py:122 templates/users_questions.html:52
msgid "using tags"
msgstr ""
@@ -1105,7 +1343,7 @@ msgstr ""
msgid "subscribe to book RSS feed"
msgstr ""
-#: templates/book.html:147 templates/index.html:118
+#: templates/book.html:147 templates/index.html:152
msgid "subscribe to the questions feed"
msgstr ""
@@ -1189,16 +1427,18 @@ msgid ""
"The reputation system allows users earn the authorization to perform a "
"variety of moderation tasks."
msgstr ""
+"Karma system allows users to earn rights to perform a variety of moderation "
+"tasks"
#: templates/faq.html:40
msgid "How does reputation system work?"
-msgstr ""
+msgstr "How does karma system work?"
#: templates/faq.html:41
msgid "Rep system summary"
msgstr ""
"When a question or answer is upvoted, the user who posted them will gain "
-"some points, which are called \"reputation points\". These points serve as a "
+"some points, which are called \"karma points\". These points serve as a "
"rough measure of the community trust to him/her. Various moderation tasks "
"are gradually assigned to the users based on those points."
@@ -1237,51 +1477,53 @@ msgstr ""
msgid "retag questions"
msgstr ""
-#: templates/faq.html:77
+#: templates/faq.html:78
msgid "edit community wiki questions"
msgstr ""
-#: templates/faq.html:81
+#: templates/faq.html:83
msgid "edit any answer"
msgstr ""
-#: templates/faq.html:85
+#: templates/faq.html:87
msgid "open any closed question"
msgstr ""
-#: templates/faq.html:89
+#: templates/faq.html:91
msgid "delete any comment"
msgstr ""
-#: templates/faq.html:93
+#: templates/faq.html:95
msgid "delete any questions and answers and perform other moderation tasks"
msgstr ""
-#: templates/faq.html:100
+#: templates/faq.html:102
msgid "how to validate email title"
msgstr "How to validate email and why?"
-#: templates/faq.html:102
-msgid "how to validate email info"
-msgstr ""
-"Why? Email validation is required to make sure that only "
-"you can post messages on your behalf and to minimize spam"
-"strong> posts. With email you can subscribe for updates "
-"on the most interesting questions. Also, when you sign up for the first time "
-"- create a unique gravatar "
-"personal image."
-
-#: templates/faq.html:106
+#: templates/faq.html:104
+#, python-format
+msgid ""
+"how to validate email info with %(send_email_key_url)s %(gravatar_faq_url)s"
+msgstr ""
+"Why? Email validation is required to make sure that "
+"only you can post messages on your behalf and to "
+"minimize spam posts. With email you can "
+"subscribe for updates on the most interesting questions. "
+"Also, when you sign up for the first time - create a unique gravatar personal image."
+
+#: templates/faq.html:108
msgid "what is gravatar"
msgstr "What is gravatar?"
-#: templates/faq.html:107
+#: templates/faq.html:109
msgid "gravatar faq info"
msgstr ""
"Gravatar means globally r"
@@ -1292,63 +1534,124 @@ msgstr ""
"your image at gravatar.com"
"strong>"
-#: templates/faq.html:110
+#: templates/faq.html:112
msgid "To register, do I need to create new password?"
msgstr ""
-#: templates/faq.html:111
+#: templates/faq.html:113
msgid ""
"No, you don't have to. You can login through any service that supports "
"OpenID, e.g. Google, Yahoo, AOL, etc."
msgstr ""
-#: templates/faq.html:112
+#: templates/faq.html:114
msgid "Login now!"
msgstr ""
-#: templates/faq.html:117
+#: templates/faq.html:119
msgid "Why other people can edit my questions/answers?"
msgstr ""
-#: templates/faq.html:118
+#: templates/faq.html:120
msgid "Goal of this site is..."
msgstr ""
-#: templates/faq.html:118
+#: templates/faq.html:120
msgid ""
"So questions and answers can be edited like wiki pages by experienced users "
"of this site and this improves the overall quality of the knowledge base "
"content."
msgstr ""
-#: templates/faq.html:119
+#: templates/faq.html:121
msgid "If this approach is not for you, we respect your choice."
msgstr ""
-#: templates/faq.html:123
+#: templates/faq.html:125
msgid "Still have questions?"
msgstr ""
-#: templates/faq.html:124
-msgid "Please ask your question, help make our community better!"
+#: templates/faq.html:126
+#, python-format
+msgid ""
+"Please ask your question at %(ask_question_url)s, help make our community "
+"better!"
msgstr ""
-"Please ask your question, help make our "
+"Please ask your question, help make our "
"community better!"
-#: templates/faq.html:126 templates/header.html:29 templates/header.html.py:63
+#: templates/faq.html:128 templates/header.html:28 templates/header.html.py:62
msgid "questions"
msgstr ""
-#: templates/faq.html:126 templates/index.html:123
+#: templates/faq.html:128 templates/index.html:157
msgid "."
msgstr ""
-#: templates/footer.html:8 templates/header.html:14 templates/index.html:83
+#: templates/feedback.html:6
+msgid "Feedback"
+msgstr ""
+
+#: templates/feedback.html:11
+msgid "Give us your feedback!"
+msgstr ""
+
+#: templates/feedback.html:17
+#, python-format
+msgid ""
+"\n"
+" Dear %(user_name)s, we look "
+"forward to hearing your feedback. \n"
+" Please type and send us your message below.\n"
+" "
+msgstr ""
+
+#: templates/feedback.html:24
+msgid ""
+"\n"
+" Dear visitor, we look forward to "
+"hearing your feedback.\n"
+" Please type and send us your message below.\n"
+" "
+msgstr ""
+
+#: templates/feedback.html:41
+msgid "(this field is required)"
+msgstr ""
+
+#: templates/feedback.html:49
+msgid "Send Feedback"
+msgstr ""
+
+#: templates/feedback_email.txt:3
+#, python-format
+msgid ""
+"\n"
+"Hello, this is a %(site_title)s forum feedback message\n"
+msgstr ""
+
+#: templates/feedback_email.txt:9
+msgid "Sender is"
+msgstr ""
+
+#: templates/feedback_email.txt:11 templates/feedback_email.txt.py:14
+msgid "email"
+msgstr ""
+
+#: templates/feedback_email.txt:13
+msgid "anonymous"
+msgstr ""
+
+#: templates/feedback_email.txt:19
+msgid "Message body:"
+msgstr ""
+
+#: templates/footer.html:8 templates/header.html:14 templates/index.html:117
msgid "about"
msgstr ""
-#: templates/footer.html:9 templates/header.html:15 templates/index.html:84
-#: templates/question_edit_tips.html:16
+#: templates/footer.html:9 templates/header.html:15 templates/index.html:118
+#: templates/question_edit_tips.html:17
msgid "faq"
msgstr ""
@@ -1368,162 +1671,176 @@ msgstr ""
msgid "privacy policy"
msgstr ""
-#: templates/footer.html:14
+#: templates/footer.html:22
msgid "give feedback"
msgstr ""
-#: templates/header.html:10
+#: templates/header.html:9
msgid "logout"
msgstr ""
-#: templates/header.html:12 templates/authopenid/signup.html:41
+#: templates/header.html:11
msgid "login"
msgstr ""
-#: templates/header.html:23
+#: templates/header.html:22
msgid "back to home page"
msgstr ""
-#: templates/header.html:31 templates/header.html.py:65
+#: templates/header.html:30 templates/header.html.py:64
msgid "users"
msgstr ""
-#: templates/header.html:33
+#: templates/header.html:32
msgid "books"
msgstr ""
-#: templates/header.html:36
+#: templates/header.html:35
msgid "unanswered questions"
msgstr "unanswered"
-#: templates/header.html:40
+#: templates/header.html:39
msgid "my profile"
msgstr ""
-#: templates/header.html:44
+#: templates/header.html:43
msgid "ask a question"
msgstr ""
-#: templates/header.html:59
+#: templates/header.html:58
msgid "search"
msgstr ""
-#: templates/index.html:7
+#: templates/index.html:8
msgid "Home"
msgstr ""
-#: templates/index.html:22 templates/questions.html:7
+#: templates/index.html:23 templates/questions.html:8
msgid "Questions"
msgstr ""
-#: templates/index.html:24
+#: templates/index.html:25
msgid "last updated questions"
msgstr ""
-#: templates/index.html:24 templates/questions.html:25
-#: templates/unanswered.html:20
+#: templates/index.html:25 templates/questions.html:26
+#: templates/unanswered.html:21
msgid "newest"
msgstr ""
-#: templates/index.html:25 templates/questions.html:27
+#: templates/index.html:26 templates/questions.html:28
msgid "hottest questions"
msgstr ""
-#: templates/index.html:25 templates/questions.html:27
+#: templates/index.html:26 templates/questions.html:28
msgid "hottest"
msgstr ""
-#: templates/index.html:26 templates/questions.html:28
+#: templates/index.html:27 templates/questions.html:29
msgid "most voted questions"
msgstr ""
-#: templates/index.html:26 templates/questions.html:28
+#: templates/index.html:27 templates/questions.html:29
msgid "most voted"
msgstr ""
-#: templates/index.html:27
+#: templates/index.html:28
msgid "all questions"
msgstr ""
-#: templates/index.html:47 templates/questions.html:45
-#: templates/unanswered.html:36 templates/users_questions.html:35
+#: templates/index.html:46 templates/question_summary_list_roll.html:13
+#: templates/questions.html:46 templates/unanswered.html:38
+#: templates/users_questions.html:36
msgid "answers"
msgstr ""
-#: templates/index.html:69 templates/question.html:499
-#: templates/questions.html:84 templates/questions.html.py:156
-#: templates/tags.html:49 templates/unanswered.html:75
-#: templates/unanswered.html.py:106 templates/users_questions.html:52
+#: templates/index.html:78 templates/index.html.py:92
+#: templates/questions.html:78 templates/questions.html.py:92
+#: templates/unanswered.html:70 templates/unanswered.html.py:84
+msgid "Posted:"
+msgstr ""
+
+#: templates/index.html:81 templates/index.html.py:86
+#: templates/questions.html:81 templates/questions.html.py:86
+#: templates/unanswered.html:73 templates/unanswered.html.py:78
+msgid "Updated:"
+msgstr ""
+
+#: templates/index.html:103 templates/question.html:480
+#: templates/question_summary_list_roll.html:52 templates/questions.html:103
+#: templates/questions.html.py:171 templates/tags.html:49
+#: templates/unanswered.html:95 templates/unanswered.html.py:122
+#: templates/users_questions.html:52
msgid "see questions tagged"
msgstr ""
-#: templates/index.html:80
+#: templates/index.html:114
msgid "welcome to website"
-msgstr ""
+msgstr "Welcome to Q&A forum"
-#: templates/index.html:89
+#: templates/index.html:123
msgid "Recent tags"
msgstr ""
-#: templates/index.html:94 templates/question.html:125
+#: templates/index.html:128 templates/question.html:135
#, python-format
msgid "see questions tagged '%(tagname)s'"
msgstr ""
-#: templates/index.html:97 templates/index.html.py:123
+#: templates/index.html:131 templates/index.html.py:157
msgid "popular tags"
msgstr "tags"
-#: templates/index.html:102
+#: templates/index.html:136
msgid "Recent awards"
msgstr "Recent badges"
-#: templates/index.html:108
+#: templates/index.html:142
msgid "given to"
msgstr ""
-#: templates/index.html:113
+#: templates/index.html:147
msgid "all awards"
msgstr "all badges"
-#: templates/index.html:118
+#: templates/index.html:152
msgid "subscribe to last 30 questions by RSS"
msgstr ""
-#: templates/index.html:123
+#: templates/index.html:157
msgid "Still looking for more? See"
msgstr ""
-#: templates/index.html:123
+#: templates/index.html:157
msgid "complete list of questions"
msgstr "list of all questions"
-#: templates/index.html:123
+#: templates/index.html:157 templates/authopenid/signup.html:18
msgid "or"
msgstr ""
-#: templates/index.html:123
+#: templates/index.html:157
msgid "Please help us answer"
msgstr ""
-#: templates/index.html:123
+#: templates/index.html:157
msgid "list of unanswered questions"
msgstr "unanswered questions"
-#: templates/logout.html:6 templates/logout.html.py:17
+#: templates/logout.html:6 templates/logout.html.py:16
msgid "Logout"
msgstr ""
-#: templates/logout.html:20
+#: templates/logout.html:19
msgid ""
"As a registered user you can login with your OpenID, log out of the site or "
"permanently remove your account."
msgstr ""
-"Clicking Logout will log you out from the Q&A forum."
-"p>
If you wish to sign off completely - please make sure to log out from "
-"your OpenID provider."
+"Clicking Logout will log you out from the forum"
+"but will not sign you off from your OpenID provider.
If you wish to sign off "
+"completely - please make sure to log out from your OpenID provider as well."
-#: templates/logout.html:21
+#: templates/logout.html:20
msgid "Logout now"
msgstr "Logout Now"
@@ -1551,6 +1868,33 @@ msgstr ""
msgid "next page"
msgstr ""
+#: templates/post_contributor_info.html:9
+#, python-format
+msgid ""
+"\n"
+" one revision\n"
+" "
+msgid_plural ""
+"\n"
+" %(rev_count)s revisions\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
+
+#: templates/post_contributor_info.html:19 templates/revisions_answer.html:66
+#: templates/revisions_question.html:66
+msgid "asked"
+msgstr ""
+
+#: templates/post_contributor_info.html:21
+msgid "answered"
+msgstr ""
+
+#: templates/post_contributor_info.html:37 templates/revisions_answer.html:68
+#: templates/revisions_question.html:68
+msgid "updated"
+msgstr ""
+
#: templates/privacy.html:6 templates/privacy.html.py:11
msgid "Privacy policy"
msgstr ""
@@ -1558,6 +1902,10 @@ msgstr ""
#: templates/privacy.html:15
msgid "general message about privacy"
msgstr ""
+"Respecting users privacy is an important core principle "
+"of this Q&A forum. "
+"Information on this page details how this forum protects your privacy, "
+"and what type of information is collected."
#: templates/privacy.html:18
msgid "Site Visitors"
@@ -1566,6 +1914,9 @@ msgstr ""
#: templates/privacy.html:20
msgid "what technical information is collected about visitors"
msgstr ""
+"Information on question views, revisions of questions and answers - both times "
+"and content are recorded for each user in order to correctly count number of views, "
+"maintain data integrity and report relevant updates."
#: templates/privacy.html:23
msgid "Personal Information"
@@ -1574,6 +1925,9 @@ msgstr ""
#: templates/privacy.html:25
msgid "details on personal information policies"
msgstr ""
+"Members of this community may choose to display personally identifiable information "
+"in their profiles. Forum will never display such information "
+"without a request from the user."
#: templates/privacy.html:28
msgid "Other Services"
@@ -1582,10 +1936,15 @@ msgstr ""
#: templates/privacy.html:30
msgid "details on sharing data with third parties"
msgstr ""
+"None of the data that is not openly shown on the forum by the choice of the user "
+"is shared with any third party."
#: templates/privacy.html:35
msgid "cookie policy details"
msgstr ""
+"Forum software relies on the internet cookie technology to "
+"keep track of user sessions. Cookies must be enabled "
+"in your browser so that forum can work for you."
#: templates/privacy.html:37
msgid "Policy Changes"
@@ -1594,194 +1953,305 @@ msgstr ""
#: templates/privacy.html:38
msgid "how privacy policies can be changed"
msgstr ""
+"These policies may be adjusted to improve protection of "
+"user's privacy. Whenever such changes occur, users will be "
+"notified via the internal messaging system. "
-#: templates/question.html:72 templates/question.html.py:73
-#: templates/question.html:85 templates/question.html.py:87
+#: templates/question.html:77 templates/question.html.py:78
+#: templates/question.html:94 templates/question.html.py:96
msgid "i like this post (click again to cancel)"
msgstr ""
-#: templates/question.html:75 templates/question.html.py:89
-#: templates/question.html:289
+#: templates/question.html:80 templates/question.html.py:98
+#: templates/question.html:257
msgid "current number of votes"
msgstr ""
-#: templates/question.html:80 templates/question.html.py:81
-#: templates/question.html:94 templates/question.html.py:95
+#: templates/question.html:89 templates/question.html.py:90
+#: templates/question.html:103 templates/question.html.py:104
msgid "i dont like this post (click again to cancel)"
msgstr ""
-#: templates/question.html:100 templates/question.html.py:101
+#: templates/question.html:109 templates/question.html.py:110
msgid "mark this question as favorite (click again to cancel)"
msgstr ""
-#: templates/question.html:107 templates/question.html.py:108
+#: templates/question.html:116 templates/question.html.py:117
msgid "remove favorite mark from this question (click again to restore mark)"
msgstr ""
-#: templates/question.html:134 templates/question.html.py:322
-#: templates/revisions_answer.html:53 templates/revisions_question.html:53
+#: templates/question.html:140 templates/question.html.py:294
+#: templates/revisions_answer.html:56 templates/revisions_question.html:56
msgid "edit"
msgstr ""
-#: templates/question.html:138 templates/question.html.py:332
+#: templates/question.html:144 templates/question.html.py:301
msgid "delete"
msgstr ""
-#: templates/question.html:143
+#: templates/question.html:149
msgid "reopen"
msgstr ""
-#: templates/question.html:148
+#: templates/question.html:153
msgid "close"
msgstr ""
-#: templates/question.html:154 templates/question.html.py:345
+#: templates/question.html:159 templates/question.html.py:308
msgid ""
"report as offensive (i.e containing spam, advertising, malicious text, etc.)"
msgstr ""
-#: templates/question.html:155 templates/question.html.py:346
+#: templates/question.html:160 templates/question.html.py:309
msgid "flag offensive"
msgstr ""
-#: templates/question.html:167 templates/question.html.py:355
-#: templates/revisions_answer.html:65 templates/revisions_question.html:65
-msgid "updated"
+#: templates/question.html:182 templates/question.html.py:331
+msgid "delete this comment"
msgstr ""
-#: templates/question.html:216 templates/question.html.py:402
-#: templates/revisions_answer.html:63 templates/revisions_question.html:63
-msgid "asked"
-msgstr ""
+#: templates/question.html:193 templates/question.html.py:342
+msgid "add comment"
+msgstr "post a comment"
-#: templates/question.html:246 templates/question.html.py:429
-msgid "comments"
-msgstr ""
+#: templates/question.html:197
+#, python-format
+msgid ""
+"\n"
+" see one more \n"
+" "
+msgid_plural ""
+"\n"
+" see %(counter)s "
+"more\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
-#: templates/question.html:247 templates/question.html.py:430
-msgid "add comment"
-msgstr ""
+#: templates/question.html:203
+#, python-format
+msgid ""
+"\n"
+" see one more "
+"comment\n"
+" "
+msgid_plural ""
+"\n"
+" see %(counter)s "
+"more comments\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
-#: templates/question.html:260
+#: templates/question.html:219
#, python-format
msgid ""
-"The question has been closed for the following reason \"%(question."
-"get_close_reason_display)s\" by"
+"The question has been closed for the following reason \"%(close_reason)s\" by"
msgstr ""
-#: templates/question.html:262
+#: templates/question.html:221
#, python-format
-msgid "close date %(question.closed_at)s"
+msgid "close date %(closed_at)s"
msgstr ""
-#: templates/question.html:269 templates/user_stats.html:13
-msgid "Answers"
-msgstr " Answers"
+#: templates/question.html:229
+#, python-format
+msgid ""
+"\n"
+" One Answer:\n"
+" "
+msgid_plural ""
+"\n"
+" %(counter)s Answers:\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
-#: templates/question.html:271
+#: templates/question.html:237
msgid "oldest answers will be shown first"
msgstr ""
-#: templates/question.html:271
+#: templates/question.html:237
msgid "oldest answers"
msgstr "oldest"
-#: templates/question.html:272
+#: templates/question.html:239
msgid "newest answers will be shown first"
msgstr ""
-#: templates/question.html:272
+#: templates/question.html:239
msgid "newest answers"
msgstr "newest"
-#: templates/question.html:273
+#: templates/question.html:241
msgid "most voted answers will be shown first"
msgstr ""
-#: templates/question.html:273
+#: templates/question.html:241
msgid "popular answers"
msgstr "most voted"
-#: templates/question.html:287 templates/question.html.py:288
+#: templates/question.html:255 templates/question.html.py:256
msgid "i like this answer (click again to cancel)"
msgstr ""
-#: templates/question.html:294 templates/question.html.py:295
+#: templates/question.html:262 templates/question.html.py:263
msgid "i dont like this answer (click again to cancel)"
msgstr ""
-#: templates/question.html:300 templates/question.html.py:301
+#: templates/question.html:268 templates/question.html.py:269
msgid "mark this answer as favorite (click again to undo)"
msgstr ""
-#: templates/question.html:306 templates/question.html.py:307
+#: templates/question.html:274 templates/question.html.py:275
msgid "the author of the question has selected this answer as correct"
msgstr ""
-#: templates/question.html:329
+#: templates/question.html:288
+msgid "answer permanent link"
+msgstr ""
+
+#: templates/question.html:289
+msgid "permanent link"
+msgstr "link"
+
+#: templates/question.html:301
msgid "undelete"
msgstr ""
-#: templates/question.html:339
-msgid "answer permanent link"
+#: templates/question.html:346
+#, python-format
+msgid ""
+"\n"
+" see one"
+"strong> more \n"
+" "
+msgid_plural ""
+"\n"
+" see %"
+"(counter)s more\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
+
+#: templates/question.html:352
+#, python-format
+msgid ""
+"\n"
+" see one"
+"strong> more comment\n"
+" "
+msgid_plural ""
+"\n"
+" see %"
+"(counter)s more comments\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
+
+#: templates/question.html:378 templates/question.html.py:381
+msgid "Notify me once a day when there are any new answers"
msgstr ""
+"Notify me once a day by email when there are any new "
+"answers or updates"
-#: templates/question.html:340
-msgid "permanent link"
+#: templates/question.html:384
+msgid "Notify me weekly when there are any new answers"
+msgstr ""
+"Notify me weekly when there are any new answers or updates"
+
+#: templates/question.html:389
+#, python-format
+msgid ""
+"\n"
+" You can always adjust frequency of email updates from your %"
+"(profile_url)s\n"
+" "
+msgstr ""
+"\n"
+"(note: you can always adjust frequency of email updates)"
+
+#: templates/question.html:396
+msgid "once you sign in you will be able to subscribe for any updates here"
msgstr ""
+"Here (once you log in) you will be able to sign "
+"up for the periodic email updates about this question."
-#: templates/question.html:453
+#: templates/question.html:407
msgid "Your answer"
msgstr ""
-#: templates/question.html:456
+#: templates/question.html:409
+msgid "Be the first one to answer this question!"
+msgstr ""
+
+#: templates/question.html:415
msgid "you can answer anonymously and then login"
msgstr ""
-"You are now not logged in but you can answer "
-"first and then login"
+"Please start posting your answer anonymously "
+"- your answer will be saved within the current session and published after "
+"you log in or create a new account. Please try to give a substantial "
+"answer, for discussions, please use comments and "
+"please do remember to vote (after you log in)!"
-#: templates/question.html:479
-msgid "Answer the question"
+#: templates/question.html:419
+msgid "answer your own question only to give an answer"
msgstr ""
+"You are welcome to answer your own question, "
+"but please make sure to give an answer. Remember that you "
+"can always revise your original question. Please "
+"use comments for discussions and please don't "
+"forget to vote :) for the answers that you liked (or perhaps did "
+"not like)! "
-#: templates/question.html:481
-msgid "Notify me daily if there are any new answers."
+#: templates/question.html:421
+msgid "please only give an answer, no discussions"
msgstr ""
+"Please try to give a substantial answer. If "
+"you wanted to comment on the question or answer, just use the "
+"commenting tool. Please remember that you can always revise "
+"your answers - no need to answer the same question twice. Also, "
+"please don't forget to vote - it really helps to select the "
+"best questions and answers!"
-#: templates/question.html:483
-msgid "once you sign in you will be able to subscribe for any updates here"
-msgstr "Here logged in users can sign up for the question updates."
+#: templates/question.html:457
+msgid "Login/Signup to Post Your Answer"
+msgstr ""
+
+#: templates/question.html:460
+msgid "Answer Your Own Question"
+msgstr ""
+
+#: templates/question.html:462
+msgid "Answer the question"
+msgstr "Post Your Answer"
-#: templates/question.html:494
+#: templates/question.html:475
msgid "Question tags"
msgstr "Tags"
-#: templates/question.html:504
+#: templates/question.html:485
msgid "question asked"
msgstr "Asked"
-#: templates/question.html:504 templates/question.html.py:510
-#: templates/user_info.html:51
-msgid "ago"
-msgstr ""
-
-#: templates/question.html:507
+#: templates/question.html:488
msgid "question was seen"
msgstr "Seen"
-#: templates/question.html:507
+#: templates/question.html:488
msgid "times"
msgstr ""
-#: templates/question.html:510
+#: templates/question.html:491
msgid "last updated"
msgstr "Last updated"
-#: templates/question.html:515
+#: templates/question.html:496
msgid "Related questions"
msgstr ""
-#: templates/question_edit.html:4 templates/question_edit.html.py:65
+#: templates/question_edit.html:5 templates/question_edit.html.py:66
msgid "Edit question"
msgstr ""
@@ -1791,57 +2261,57 @@ msgstr "Tips"
#: templates/question_edit_tips.html:7
msgid "please ask a relevant question"
-msgstr ""
+msgstr "ask a question relevant to the CNPROG community"
#: templates/question_edit_tips.html:10
msgid "please try provide enough details"
msgstr "provide enough details"
-#: templates/question_retag.html:3 templates/question_retag.html.py:52
+#: templates/question_retag.html:4 templates/question_retag.html.py:53
msgid "Change tags"
msgstr ""
-#: templates/question_retag.html:39
+#: templates/question_retag.html:40
msgid "up to 5 tags, less than 20 characters each"
msgstr ""
-#: templates/question_retag.html:82
+#: templates/question_retag.html:83
msgid "Why use and modify tags?"
msgstr ""
-#: templates/question_retag.html:85
+#: templates/question_retag.html:86
msgid "tags help us keep Questions organized"
msgstr ""
-#: templates/question_retag.html:91
+#: templates/question_retag.html:94
msgid "tag editors receive special awards from the community"
msgstr ""
-#: templates/questions.html:23
+#: templates/questions.html:24
msgid "Found by tags"
msgstr "Tagged questions"
-#: templates/questions.html:23
+#: templates/questions.html:24
msgid "Found by title"
msgstr ""
-#: templates/questions.html:23
+#: templates/questions.html:24
msgid "All questions"
msgstr ""
-#: templates/questions.html:25 templates/unanswered.html:20
+#: templates/questions.html:26 templates/unanswered.html:21
msgid "most recently asked questions"
msgstr ""
-#: templates/questions.html:26
+#: templates/questions.html:27
msgid "most recently updated questions"
msgstr ""
-#: templates/questions.html:26
+#: templates/questions.html:27
msgid "active"
msgstr ""
-#: templates/questions.html:109
+#: templates/questions.html:126
#, python-format
msgid ""
"\n"
@@ -1860,7 +2330,7 @@ msgstr[1] ""
"
"
-#: templates/questions.html:131
+#: templates/questions.html:148
msgid "latest questions info"
msgstr "Newest questions are shown first."
-#: templates/questions.html:135
+#: templates/questions.html:152
msgid "Questions are sorted by the time of last update."
msgstr ""
-#: templates/questions.html:136
+#: templates/questions.html:153
msgid "Most recently answered ones are shown first."
msgstr "Most recently answered questions are shown first."
-#: templates/questions.html:140
+#: templates/questions.html:157
msgid "Questions sorted by number of responses."
msgstr "Questions sorted by the number of answers."
-#: templates/questions.html:141
+#: templates/questions.html:158
msgid "Most answered questions are shown first."
msgstr " "
-#: templates/questions.html:145
+#: templates/questions.html:162
msgid "Questions are sorted by the number of votes."
msgstr ""
-#: templates/questions.html:146
+#: templates/questions.html:163
msgid "Most voted questions are shown first."
msgstr ""
-#: templates/questions.html:153 templates/unanswered.html:102
+#: templates/questions.html:168 templates/unanswered.html:118
msgid "Related tags"
msgstr "Tags"
@@ -1963,6 +2433,10 @@ msgstr ""
msgid "Revision history"
msgstr ""
+#: templates/revisions_answer.html:48 templates/revisions_question.html:48
+msgid "click to hide/show revision"
+msgstr ""
+
#: templates/tags.html:6 templates/tags.html.py:30
msgid "Tag list"
msgstr ""
@@ -1995,16 +2469,16 @@ msgstr ""
msgid "Nothing found"
msgstr ""
-#: templates/unanswered.html:7 templates/unanswered.html.py:18
+#: templates/unanswered.html:8 templates/unanswered.html.py:19
msgid "Unanswered questions"
msgstr ""
-#: templates/unanswered.html:97
+#: templates/unanswered.html:114
#, python-format
msgid "have %(num_q)s unanswered questions"
msgstr ""
-"
%(num_q)s
unanswered "
-"questions"
+"
%(num_q)s
questions without "
+"accepted answers"
#: templates/user_edit.html:6
msgid "Edit user profile"
@@ -2019,139 +2493,202 @@ msgid "image associated with your email address"
msgstr ""
#: templates/user_edit.html:31
-msgid "avatar"
-msgstr "gravatar"
+#, python-format
+msgid "avatar, see %(gravatar_faq_url)s"
+msgstr "gravatar"
-#: templates/user_edit.html:36 templates/user_info.html:31
+#: templates/user_edit.html:36 templates/user_info.html:56
msgid "Registered user"
msgstr ""
-#: templates/user_edit.html:82
+#: templates/user_edit.html:82 templates/user_email_subscriptions.html:17
msgid "Update"
msgstr ""
-#: templates/user_info.html:34
+#: templates/user_email_subscriptions.html:8
+msgid "Email subscription settings"
+msgstr ""
+
+#: templates/user_email_subscriptions.html:9
+msgid "email subscription settings info"
+msgstr ""
+"Adjust frequency of email updates. Receive "
+"updates on interesting questions by email, help the community"
+"strong> by answering questions of your colleagues. If you do not wish to "
+"receive emails - select 'no email' on all items below. Updates are only "
+"sent when there is any new activity on selected items."
+
+#: templates/user_email_subscriptions.html:18
+msgid "Stop sending email"
+msgstr "Stop Email"
+
+#: templates/user_info.html:32
+msgid "Moderate this user"
+msgstr ""
+
+#: templates/user_info.html:45
msgid "update profile"
msgstr ""
-#: templates/user_info.html:40
+#: templates/user_info.html:60
msgid "real name"
msgstr ""
-#: templates/user_info.html:45
+#: templates/user_info.html:65
msgid "member for"
-msgstr ""
+msgstr "member since"
-#: templates/user_info.html:50
+#: templates/user_info.html:70
msgid "last seen"
msgstr ""
-#: templates/user_info.html:56
+#: templates/user_info.html:76
msgid "user website"
msgstr ""
-#: templates/user_info.html:62
+#: templates/user_info.html:82
msgid "location"
msgstr ""
-#: templates/user_info.html:69
+#: templates/user_info.html:89
msgid "age"
msgstr ""
-#: templates/user_info.html:70
+#: templates/user_info.html:90
msgid "age unit"
msgstr "years old"
-#: templates/user_info.html:76
+#: templates/user_info.html:96
msgid "todays unused votes"
msgstr ""
-#: templates/user_info.html:77
+#: templates/user_info.html:97
msgid "votes left"
msgstr ""
-#: templates/user_preferences.html:10
-msgid "Connect with Twitter"
-msgstr ""
-
-#: templates/user_preferences.html:13
-msgid "Twitter account name:"
-msgstr ""
-
-#: templates/user_preferences.html:15
-msgid "Twitter password:"
-msgstr ""
-
-#: templates/user_preferences.html:17
-msgid "Send my Questions to Twitter"
-msgstr ""
-
-#: templates/user_preferences.html:18
-msgid "Send my Answers to Twitter"
-msgstr ""
-
-#: templates/user_preferences.html:19
-msgid "Save"
-msgstr ""
+#: templates/user_stats.html:12
+#, python-format
+msgid ""
+"\n"
+" 1 Question\n"
+" "
+msgid_plural ""
+"\n"
+" %(counter)s Questions\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
-#: templates/user_stats.html:10
-msgid "User questions"
-msgstr ""
+#: templates/user_stats.html:23
+#, python-format
+msgid ""
+"\n"
+" 1 Answer\n"
+" "
+msgid_plural ""
+"\n"
+" %(counter)s Answers\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
-#: templates/user_stats.html:20
+#: templates/user_stats.html:36
#, python-format
msgid "the answer has been voted for %(vote_count)s times"
msgstr ""
-#: templates/user_stats.html:20
+#: templates/user_stats.html:36
msgid "this answer has been selected as correct"
msgstr ""
-#: templates/user_stats.html:28
+#: templates/user_stats.html:46
#, python-format
-msgid "the answer has been commented %(comment_count)s times"
-msgstr ""
+msgid ""
+"\n"
+" (one comment)\n"
+" "
+msgid_plural ""
+"\n"
+" the answer has been commented %(comment_count)s times\n"
+" "
+msgstr[0] ""
+"\n"
+"(one comment)"
+msgstr[1] ""
+"\n"
+"(%(comment_count)s comments)"
-#: templates/user_stats.html:36
-msgid "Votes"
-msgstr ""
+#: templates/user_stats.html:61
+#, python-format
+msgid ""
+"\n"
+" 1 Vote\n"
+" "
+msgid_plural ""
+"\n"
+" %(cnt)s Votes\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
-#: templates/user_stats.html:41
+#: templates/user_stats.html:72
msgid "thumb up"
msgstr ""
-#: templates/user_stats.html:42
+#: templates/user_stats.html:73
msgid "user has voted up this many times"
msgstr ""
-#: templates/user_stats.html:46
+#: templates/user_stats.html:77
msgid "thumb down"
msgstr ""
-#: templates/user_stats.html:47
+#: templates/user_stats.html:78
msgid "user voted down this many times"
msgstr ""
-#: templates/user_stats.html:54
-msgid "Tags"
-msgstr ""
+#: templates/user_stats.html:87
+#, python-format
+msgid ""
+"\n"
+" 1 Tag\n"
+" "
+msgid_plural ""
+"\n"
+" %(counter)s Tags\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
-#: templates/user_stats.html:61
+#: templates/user_stats.html:100
#, python-format
msgid "see other questions tagged '%(tag)s' "
msgstr ""
+#: templates/user_stats.html:114
+#, python-format
+msgid ""
+"\n"
+" 1 Badge\n"
+" "
+msgid_plural ""
+"\n"
+" %(counter)s Badges\n"
+" "
+msgstr[0] ""
+msgstr[1] ""
+
#: templates/user_tabs.html:7
msgid "User profile"
msgstr ""
#: templates/user_tabs.html:16
msgid "graph of user reputation"
-msgstr ""
+msgstr "Graph of user karma"
#: templates/user_tabs.html:17
msgid "reputation history"
-msgstr ""
+msgstr "karma history"
#: templates/user_tabs.html:23
msgid "questions that user selected as his/her favorite"
@@ -2161,10 +2698,6 @@ msgstr ""
msgid "favorites"
msgstr ""
-#: templates/user_tabs.html:28
-msgid "settings"
-msgstr ""
-
#: templates/users.html:6 templates/users.html.py:24
msgid "Users"
msgstr ""
@@ -2202,16 +2735,21 @@ msgstr ""
msgid "thumb-up off"
msgstr ""
-#: templates/users_questions.html:35
+#: templates/users_questions.html:34
msgid "this answer has been accepted to be correct"
msgstr ""
-#: templates/authopenid/changeemail.html:7
-#: templates/authopenid/changeemail.html:33
+#: templates/authopenid/changeemail.html:3
+#: templates/authopenid/changeemail.html:9
+#: templates/authopenid/changeemail.html:38
msgid "Change email"
msgstr "Change Email"
-#: templates/authopenid/changeemail.html:10
+#: templates/authopenid/changeemail.html:11
+msgid "Save your email address"
+msgstr ""
+
+#: templates/authopenid/changeemail.html:16
#, python-format
msgid "change %(email)s info"
msgstr ""
@@ -2219,57 +2757,66 @@ msgstr ""
"you'd like to use another email for update subscriptions."
" Currently you are using %(email)s"
-#: templates/authopenid/changeemail.html:13
-#: templates/authopenid/changeopenid.html:14
-#: templates/authopenid/changepw.html:19 templates/authopenid/delete.html:15
-#: templates/authopenid/delete.html:25
-msgid "Please correct errors below:"
+#: templates/authopenid/changeemail.html:18
+#, python-format
+msgid "here is why email is required, see %(gravatar_faq_url)s"
msgstr ""
+"Please enter your email address in the box below."
+"span> Valid email address is required on this Q&"
+"A forum. If you like, you can receive updates on "
+"interesting questions or entire forum via email. Also, your email is used to "
+"create a unique gravatar "
+"image for your account. Email addresses are never shown or otherwise shared "
+"with anybody else."
-#: templates/authopenid/changeemail.html:30
+#: templates/authopenid/changeemail.html:31
msgid "Your new Email"
msgstr ""
"Your new Email: (will not be shown to "
"anyone, must be valid)"
#: templates/authopenid/changeemail.html:31
-#: templates/authopenid/signin.html:154
-msgid "Password"
+msgid "Your Email"
msgstr ""
+"Your Email (must be valid, never shown to others)"
-#: templates/authopenid/changeemail.html:42
+#: templates/authopenid/changeemail.html:38
+msgid "Save Email"
+msgstr ""
+
+#: templates/authopenid/changeemail.html:49
msgid "Validate email"
msgstr ""
-#: templates/authopenid/changeemail.html:45
+#: templates/authopenid/changeemail.html:52
#, python-format
-msgid "validate %(email)s info"
+msgid "validate %(email)s info or go to %(change_email_url)s"
msgstr ""
"An email with a validation link has been sent to %"
"(email)s. Please follow the emailed link with your "
"web browser. Email validation is necessary to help insure the proper use of "
-"email on Q&A forum. If you would like "
-"to use another email, please change it again."
+"email on Q&A. If you would like "
+"to use another email, please change it again."
-#: templates/authopenid/changeemail.html:50
+#: templates/authopenid/changeemail.html:57
msgid "Email not changed"
msgstr ""
-#: templates/authopenid/changeemail.html:53
+#: templates/authopenid/changeemail.html:60
#, python-format
-msgid "old %(email)s kept"
+msgid "old %(email)s kept, if you like go to %(change_email_url)s"
msgstr ""
"Your email address %(email)s has not been changed."
" If you decide to change it later - you can always do it by editing "
-"it in your user profile or by using the previous form again."
+"it in your user profile or by using the previous form again."
-#: templates/authopenid/changeemail.html:58
+#: templates/authopenid/changeemail.html:65
msgid "Email changed"
msgstr ""
-#: templates/authopenid/changeemail.html:61
+#: templates/authopenid/changeemail.html:68
#, python-format
msgid "your current %(email)s can be used for this"
msgstr ""
@@ -2278,11 +2825,11 @@ msgstr ""
"Email notifications are sent once a day or less frequently - only when there "
"are any news."
-#: templates/authopenid/changeemail.html:66
+#: templates/authopenid/changeemail.html:73
msgid "Email verified"
msgstr ""
-#: templates/authopenid/changeemail.html:69
+#: templates/authopenid/changeemail.html:76
msgid "thanks for verifying email"
msgstr ""
"Thank you for verifying your email! Now "
@@ -2291,11 +2838,11 @@ msgstr ""
"updates - then will be notified about changes once a day"
"strong> or less frequently."
-#: templates/authopenid/changeemail.html:74
+#: templates/authopenid/changeemail.html:81
msgid "email key not sent"
msgstr "Validation email not sent"
-#: templates/authopenid/changeemail.html:77
+#: templates/authopenid/changeemail.html:84
#, python-format
msgid "email key not sent %(email)s change email here %(change_link)s"
msgstr ""
@@ -2303,6 +2850,12 @@ msgstr ""
"validated before so the new key was not sent. You can change email used for update subscriptions if necessary."
+#: templates/authopenid/changeopenid.html:4
+#: templates/authopenid/changeopenid.html:30
+#: templates/authopenid/settings.html:34
+msgid "Change OpenID"
+msgstr ""
+
#: templates/authopenid/changeopenid.html:8
msgid "Account: change OpenID URL"
msgstr ""
@@ -2312,97 +2865,129 @@ msgid ""
"This is where you can change your OpenID URL. Make sure you remember it!"
msgstr ""
+#: templates/authopenid/changeopenid.html:14
+#: templates/authopenid/delete.html:14 templates/authopenid/delete.html:24
+msgid "Please correct errors below:"
+msgstr ""
+
#: templates/authopenid/changeopenid.html:29
msgid "OpenID URL:"
msgstr ""
-#: templates/authopenid/changeopenid.html:30
-msgid "Change OpenID"
+#: templates/authopenid/changepw.html:5 templates/authopenid/changepw.html:14
+#: templates/authopenid/settings.html:29
+msgid "Change password"
msgstr ""
-#: templates/authopenid/changepw.html:14
+#: templates/authopenid/changepw.html:7
msgid "Account: change password"
-msgstr ""
+msgstr "Change your password"
-#: templates/authopenid/changepw.html:17
+#: templates/authopenid/changepw.html:8
msgid "This is where you can change your password. Make sure you remember it!"
msgstr ""
+"To change your password please fill out and "
+"submit this form"
-#: templates/authopenid/changepw.html:27
-msgid "Current password"
-msgstr ""
-
-#: templates/authopenid/changepw.html:28
-msgid "New password"
-msgstr ""
-
-#: templates/authopenid/changepw.html:29
-msgid "New password again"
-msgstr ""
-
-#: templates/authopenid/changepw.html:30 templates/authopenid/settings.html:29
-msgid "Change password"
-msgstr ""
-
-#: templates/authopenid/complete.html:5
+#: templates/authopenid/complete.html:19
msgid "Connect your OpenID with this site"
msgstr "New user signup"
-#: templates/authopenid/complete.html:8
+#: templates/authopenid/complete.html:22
msgid "Connect your OpenID with your account on this site"
msgstr "New user signup"
-#: templates/authopenid/complete.html:12
+#: templates/authopenid/complete.html:27
#, python-format
-msgid "register new %(provider)s account info"
+msgid "register new %(provider)s account info, see %(gravatar_faq_url)s"
msgstr ""
"
You are here for the first time with your %"
"(provider)s login. Please create your screen name "
"and save your email address. Saved email address will let "
"you subscribe for the updates on the most interesting "
"questions and will be used to create and retrieve your unique avatar image - "
-"gravatar."
+"gravatar.
"
-#: templates/authopenid/complete.html:14
+#: templates/authopenid/complete.html:31
+#, python-format
+msgid ""
+"%(username)s already exists, choose another name for \n"
+" %(provider)s. Email is required too, see %"
+"(gravatar_faq_url)s\n"
+" "
+msgstr ""
+"
Oops... looks like screen name %(username)s is "
+"already used in another account.
Please choose another screen name "
+"to use with your %(provider)s login. Also, a valid email address is "
+"required on the Q&A forum. Your "
+"email is used to create a unique gravatar image for your account. If you like, "
+"you can receive updates on the interesting questions or "
+"entire forum by email. Email addresses are never shown or otherwise shared "
+"with anybody else.
"
+
+#: templates/authopenid/complete.html:35
+#, python-format
+msgid ""
+"register new external %(provider)s account info, see %(gravatar_faq_url)s"
+msgstr ""
+"
You are here for the first time with your %"
+"(provider)s login.
You can either keep your screen "
+"name the same as your %(provider)s login name or choose some other "
+"nickname.
Also, please save a valid email address. "
+"With the email you can subscribe for the updates on the "
+"most interesting questions. Email address is also used to create and "
+"retrieve your unique avatar image - gravatar.
"
+
+#: templates/authopenid/complete.html:40
msgid "This account already exists, please use another."
msgstr ""
-#: templates/authopenid/complete.html:19 templates/authopenid/complete.html:32
-#: templates/authopenid/signin.html:138
+#: templates/authopenid/complete.html:55
msgid "Sorry, looks like we have some errors:"
msgstr ""
-#: templates/authopenid/complete.html:47
+#: templates/authopenid/complete.html:76
msgid "Screen name label"
msgstr "Screen Name (will be shown to others)"
-#: templates/authopenid/complete.html:48
+#: templates/authopenid/complete.html:83
msgid "Email address label"
msgstr ""
"Email Address (will not be shared with "
"anyone, must be valid)"
-#: templates/authopenid/complete.html:49
+#: templates/authopenid/complete.html:89 templates/authopenid/signup.html:15
+msgid "receive updates motivational blurb"
+msgstr ""
+"Receive forum updates by email - this will help our "
+"community grow and become more useful. By default "
+"Q&A forum sends up to one "
+"email digest per week - only when there is anything new. If "
+"you like, please adjust this now or any time later from your user account."
+
+#: templates/authopenid/complete.html:91
msgid "create account"
msgstr "Signup"
-#: templates/authopenid/complete.html:56
+#: templates/authopenid/complete.html:100
msgid "Existing account"
msgstr ""
-#: templates/authopenid/complete.html:57
+#: templates/authopenid/complete.html:101
msgid "user name"
msgstr ""
-#: templates/authopenid/complete.html:58 templates/authopenid/signin.html:128
+#: templates/authopenid/complete.html:102
msgid "password"
msgstr ""
-#: templates/authopenid/complete.html:61
+#: templates/authopenid/complete.html:107
msgid "Register"
msgstr ""
-#: templates/authopenid/complete.html:62 templates/authopenid/signin.html:156
+#: templates/authopenid/complete.html:108 templates/authopenid/signin.html:140
msgid "Forgot your password?"
msgstr ""
@@ -2415,12 +3000,11 @@ msgid "Your account details are:"
msgstr ""
#: templates/authopenid/confirm_email.txt:6
-#: templates/authopenid/sendpw_email.txt:7
msgid "Username:"
msgstr ""
#: templates/authopenid/confirm_email.txt:7
-#: templates/authopenid/delete.html:20
+#: templates/authopenid/delete.html:19
msgid "Password:"
msgstr ""
@@ -2430,45 +3014,51 @@ msgstr ""
#: templates/authopenid/confirm_email.txt:12
#: templates/authopenid/email_validation.txt:14
-#: templates/authopenid/sendpw_email.txt:13
+#: templates/authopenid/sendpw_email.txt:8
msgid ""
"Sincerely,\n"
"Forum Administrator"
msgstr ""
+"Sincerely,\n"
+"Q&A Forum Administrator"
+
+#: templates/authopenid/delete.html:4 templates/authopenid/settings.html:38
+msgid "Delete account"
+msgstr ""
-#: templates/authopenid/delete.html:9
+#: templates/authopenid/delete.html:8
msgid "Account: delete account"
msgstr ""
-#: templates/authopenid/delete.html:13
+#: templates/authopenid/delete.html:12
msgid ""
"Note: After deleting your account, anyone will be able to register this "
"username."
msgstr ""
-#: templates/authopenid/delete.html:17
+#: templates/authopenid/delete.html:16
msgid "Check confirm box, if you want delete your account."
msgstr ""
-#: templates/authopenid/delete.html:32
+#: templates/authopenid/delete.html:31
msgid "I am sure I want to delete my account."
msgstr ""
-#: templates/authopenid/delete.html:33
+#: templates/authopenid/delete.html:32
msgid "Password/OpenID URL"
msgstr ""
-#: templates/authopenid/delete.html:33
+#: templates/authopenid/delete.html:32
msgid "(required for your security)"
msgstr ""
-#: templates/authopenid/delete.html:35
+#: templates/authopenid/delete.html:34
msgid "Delete account permanently"
msgstr ""
#: templates/authopenid/email_validation.txt:2
msgid "Greetings from the Q&A forum"
-msgstr "Greetings from the Q&A forum"
+msgstr ""
#: templates/authopenid/email_validation.txt:4
msgid "To make use of the Forum, please follow the link below:"
@@ -2485,38 +3075,33 @@ msgid ""
"for any inconvenience"
msgstr ""
-#: templates/authopenid/sendpw.html:4 templates/authopenid/sendpw.html.py:8
-msgid "Send new password"
-msgstr ""
-
-#: templates/authopenid/sendpw.html:12
-msgid "Lost your password? No problem - here you can reset it."
+#: templates/authopenid/external_legacy_login_info.html:4
+#: templates/authopenid/external_legacy_login_info.html:7
+msgid "Traditional login information"
msgstr ""
-#: templates/authopenid/sendpw.html:13
-msgid ""
-"Please enter your username below and new password will be sent to your "
-"registered e-mail"
-msgstr ""
+#: templates/authopenid/sendpw.html:4 templates/authopenid/sendpw.html.py:7
+msgid "Send new password"
+msgstr "Recover password"
-#: templates/authopenid/sendpw.html:28
-msgid "User name"
+#: templates/authopenid/sendpw.html:10
+msgid "password recovery information"
msgstr ""
+"Forgot you password? No problems - just get a new "
+"one! Please follow the following steps: • submit your "
+"user name below and check your email • follow the "
+"activation link for the new password - sent to you by email and "
+"login with the suggested password • at this you might want to "
+"change your password to something you can remember better"
-#: templates/authopenid/sendpw.html:30
+#: templates/authopenid/sendpw.html:21
msgid "Reset password"
-msgstr ""
+msgstr "Send me a new password"
-#: templates/authopenid/sendpw.html:30
+#: templates/authopenid/sendpw.html:22
msgid "return to login"
msgstr ""
-#: templates/authopenid/sendpw.html:33
-msgid ""
-"Note: your new password will be activated only after you click the "
-"activation link in the email message"
-msgstr ""
-
#: templates/authopenid/sendpw_email.txt:2
#, python-format
msgid ""
@@ -2525,15 +3110,18 @@ msgid ""
msgstr ""
#: templates/authopenid/sendpw_email.txt:5
-msgid "Your new account details are:"
-msgstr ""
-
-#: templates/authopenid/sendpw_email.txt:8
-msgid "New password:"
+#, python-format
+msgid ""
+"email explanation how to use new %(password)s for %(username)s\n"
+"with the %(key_link)s"
msgstr ""
+"To change your password, please follow these steps:\n"
+"* visit this link: %(key_link)s\n"
+"* login with user name %(username)s and password %(password)s\n"
+"* go to your user profile and set the password to something you can remember"
-#: templates/authopenid/sendpw_email.txt:10
-msgid "To confirm that you wanted to reset your password please visit:"
+#: templates/authopenid/settings.html:4
+msgid "Account functions"
msgstr ""
#: templates/authopenid/settings.html:30
@@ -2552,15 +3140,11 @@ msgstr ""
msgid "Change openid associated to your account"
msgstr ""
-#: templates/authopenid/settings.html:38
-msgid "Delete account"
-msgstr ""
-
#: templates/authopenid/settings.html:39
msgid "Erase your username and all your data from website"
msgstr ""
-#: templates/authopenid/signin.html:4 templates/authopenid/signin.html:21
+#: templates/authopenid/signin.html:5 templates/authopenid/signin.html:21
msgid "User login"
msgstr "User login"
@@ -2588,148 +3172,105 @@ msgstr ""
"strong> %(summary)s...\" is saved and will be "
"posted once you log in."
-#: templates/authopenid/signin.html:40
+#: templates/authopenid/signin.html:42
msgid "Click to sign in through any of these services."
msgstr ""
-"
Please select your favorite login method below."
-"
External login services use OpenID technology that increases "
-"security of your online identity and makes login process simpler. First option "
-"requires login name and password.
"
+"
Please select your favorite login method below."
+"
External login services use OpenID technology, where your password "
+"always stays confidential between you and your login provider and you don't "
+"have to remember another one. CNPROG option requires your login name and "
+"password entered here.
"
-#: templates/authopenid/signin.html:113
+#: templates/authopenid/signin.html:117
msgid "Enter your Provider user name"
msgstr ""
-"Enter your Provider "
-"user name (or select another login method above)"
+"Enter your Provider user name (or "
+"select another login method above)"
-#: templates/authopenid/signin.html:120
+#: templates/authopenid/signin.html:124
msgid ""
"Enter your OpenID "
"web address"
msgstr ""
"Enter your OpenID web address (or choose another login "
-"method above)"
+"openid.net\">OpenID web address (or choose "
+"another login method above)"
-#: templates/authopenid/signin.html:122 templates/authopenid/signin.html:130
-#: templates/authopenid/signin.html:155
+#: templates/authopenid/signin.html:126 templates/authopenid/signin.html:138
msgid "Login"
msgstr ""
-#: templates/authopenid/signin.html:125
+#: templates/authopenid/signin.html:129
msgid "Enter your login name and password"
msgstr ""
-"Enter your forum login and password "
-"(or select your OpenID provider above)"
-
-#: templates/authopenid/signin.html:126
-msgid "login name"
-msgstr ""
-
-#: templates/authopenid/signin.html:134
-msgid "we support two login modes"
-msgstr ""
-"You can log in either through one of these services or traditionally - using "
-"local username/password."
+"Enter your CNPROG login and password (or select your OpenID provider above)"
-#: templates/authopenid/signin.html:152
-msgid "Use login name and password"
+#: templates/authopenid/signin.html:133
+msgid "Login name"
msgstr ""
-#: templates/authopenid/signin.html:153
-msgid "Login name"
+#: templates/authopenid/signin.html:135
+msgid "Password"
msgstr ""
-#: templates/authopenid/signin.html:157
-msgid "Create new account"
+#: templates/authopenid/signin.html:139
+msgid "Create account"
msgstr ""
-#: templates/authopenid/signin.html:166
+#: templates/authopenid/signin.html:149
msgid "Why use OpenID?"
msgstr ""
-#: templates/authopenid/signin.html:169
+#: templates/authopenid/signin.html:152
msgid "with openid it is easier"
msgstr "With the OpenID you don't need to create new username and password."
-#: templates/authopenid/signin.html:172
+#: templates/authopenid/signin.html:155
msgid "reuse openid"
msgstr "You can safely re-use the same login for all OpenID-enabled websites."
-#: templates/authopenid/signin.html:175
+#: templates/authopenid/signin.html:158
msgid "openid is widely adopted"
msgstr ""
"There are > 160,000,000 OpenID account in use. Over 10,000 sites are OpenID-"
"enabled."
-#: templates/authopenid/signin.html:178
+#: templates/authopenid/signin.html:161
msgid "openid is supported open standard"
msgstr "OpenID is based on an open standard, supported by many organizations."
-#: templates/authopenid/signin.html:183
+#: templates/authopenid/signin.html:166
msgid "Find out more"
msgstr ""
-#: templates/authopenid/signin.html:184
+#: templates/authopenid/signin.html:167
msgid "Get OpenID"
msgstr ""
-#: templates/authopenid/signup.html:4 templates/authopenid/signup.html.py:8
+#: templates/authopenid/signup.html:4
msgid "Signup"
msgstr ""
-#: templates/authopenid/signup.html:12
-msgid ""
-"We support two types of user registration: conventional username/password, "
-"and"
+#: templates/authopenid/signup.html:8
+msgid "Create login name and password"
msgstr ""
-#: templates/authopenid/signup.html:12
-msgid "the OpenID method"
+#: templates/authopenid/signup.html:10
+msgid "Traditional signup info"
msgstr ""
+"If you prefer, create your forum login name and "
+"password here. However, please keep in mind that we also support "
+"OpenID login method. With OpenID you can "
+"simply reuse your external login (e.g. Gmail or AOL) without ever sharing "
+"your login details with anyone and having to remember yet another password."
#: templates/authopenid/signup.html:17
-msgid "Sorry, looks like we have some errors"
-msgstr ""
-
-#: templates/authopenid/signup.html:35
-msgid "Conventional registration"
-msgstr ""
-
-#: templates/authopenid/signup.html:36
-msgid "choose a user name"
-msgstr ""
-
-#: templates/authopenid/signup.html:42
-msgid "back to login"
+msgid "Create Account"
msgstr ""
-#: templates/authopenid/signup.html:46
-msgid "Register with your OpenID"
+#: templates/authopenid/signup.html:19
+msgid "return to OpenID login"
msgstr ""
-
-#: templates/authopenid/signup.html:49
-msgid "Login with your OpenID"
-msgstr ""
-
-#
-#~ msgid "editing tips"
-#~ msgstr "Tips"
-
-#~ msgid "Newest questions shown first."
-#~ msgstr ""
-#~ "Questions are sorted by entry date.Newest questions "
-#~ "shown first."
-
-#~ msgid ""
-#~ "please use space to separate tags (this enables autocomplete feature)"
-#~ msgstr "please use space to separate tags (uses autocomplete utility)"
-
-#~ msgid "select openid provider"
-#~ msgstr "1) Please select your id service provider."
-
-#~ msgid "verify openid link and login"
-#~ msgstr ""
-#~ "2) Please verify the OpenID URL (type your login name over {username}, if "
-#~ "present) and then log in."
diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo
index 91639ba1..fc7ebe14 100644
Binary files a/locale/es/LC_MESSAGES/django.mo and b/locale/es/LC_MESSAGES/django.mo differ
diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po
index d7655dd7..b528fcf2 100644
--- a/locale/es/LC_MESSAGES/django.po
+++ b/locale/es/LC_MESSAGES/django.po
@@ -2,21 +2,22 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-08-17 16:44+0000\n"
-"PO-Revision-Date: 2009-08-17 10:04-0600\n"
+"POT-Creation-Date: 2009-08-12 15:53+0000\n"
+"PO-Revision-Date: \n"
"Last-Translator: Bruno Sarlo \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: settings.py:12 urls.py:25 forum/views.py:310 forum/views.py:705
+#: settings.py:12 urls.py:25 forum/views.py:304 forum/views.py:698
msgid "account/"
msgstr "cuenta/"
#: settings.py:12 urls.py:26 django_authopenid/urls.py:9
#: django_authopenid/urls.py:10 django_authopenid/urls.py:11
-#: django_authopenid/urls.py:13 forum/views.py:310 forum/views.py:706
+#: django_authopenid/urls.py:13 forum/views.py:304 forum/views.py:699
+#: templates/authopenid/confirm_email.txt:10
msgid "signin/"
msgstr "ingresar/"
@@ -24,132 +25,127 @@ msgstr "ingresar/"
msgid "upfiles/"
msgstr "archivossubidos/"
-#: urls.py:27 django_authopenid/urls.py:16
-msgid "signup/"
-msgstr "registrarse/"
-
-#: urls.py:28 urls.py:29 urls.py:30 django_authopenid/urls.py:26
+#: urls.py:27 urls.py:28 urls.py:29 django_authopenid/urls.py:26
#: django_authopenid/urls.py:27
msgid "email/"
msgstr "email/"
-#: urls.py:28
+#: urls.py:27
msgid "change/"
msgstr "cambiar/"
-#: urls.py:29
+#: urls.py:28
msgid "sendkey/"
msgstr "enviarclave/"
-#: urls.py:30
+#: urls.py:29
msgid "verify/"
msgstr "verificar/"
-#: urls.py:31
+#: urls.py:30
msgid "about/"
msgstr "acercadenosotros/"
-#: urls.py:32
+#: urls.py:31
msgid "faq/"
msgstr "preguntasfrecuentes/"
-#: urls.py:33
+#: urls.py:32
msgid "privacy/"
msgstr "códigodeprivacidad/"
-#: urls.py:34
+#: urls.py:33
msgid "logout/"
msgstr "cerrarsesion/"
-#: urls.py:35 urls.py:36 urls.py:37 urls.py:49 forum/models.py:425
+#: urls.py:34 urls.py:35 urls.py:36 urls.py:48 forum/models.py:418
msgid "answers/"
msgstr "respuestas/"
-#: urls.py:35 urls.py:47
+#: urls.py:34 urls.py:46
msgid "comments/"
msgstr "comentarios/"
-#: urls.py:36 urls.py:41 urls.py:55 templates/user_info.html:34
+#: urls.py:35 urls.py:40 urls.py:54 templates/user_info.html:34
msgid "edit/"
msgstr "editar/"
-#: urls.py:37 urls.py:46
+#: urls.py:36 urls.py:45
msgid "revisions/"
msgstr "revisiones/"
-#: urls.py:38 urls.py:39 urls.py:40 urls.py:41 urls.py:42 urls.py:43
-#: urls.py:44 urls.py:45 urls.py:46 urls.py:47 urls.py:48 forum/feed.py:19
-#: forum/models.py:313 forum/views.py:1232 forum/views.py:1234
-#: forum/views.py:1474
+#: urls.py:37 urls.py:38 urls.py:39 urls.py:40 urls.py:41 urls.py:42
+#: urls.py:43 urls.py:44 urls.py:45 urls.py:46 urls.py:47 forum/feed.py:19
+#: forum/models.py:306 forum/views.py:1416
msgid "questions/"
msgstr "preguntas/"
-#: urls.py:39 urls.py:65
+#: urls.py:38 urls.py:64
msgid "ask/"
msgstr "preguntar/"
-#: urls.py:40
+#: urls.py:39
msgid "unanswered/"
msgstr "sinrespuesta/"
-#: urls.py:42
+#: urls.py:41
msgid "close/"
msgstr "cerrar/"
-#: urls.py:43
+#: urls.py:42
msgid "reopen/"
msgstr "reabrir/"
-#: urls.py:44
+#: urls.py:43
msgid "answer/"
msgstr "respuesta/"
-#: urls.py:45
+#: urls.py:44
msgid "vote/"
msgstr "votar/"
-#: urls.py:48 urls.py:49 django_authopenid/urls.py:29
+#: urls.py:47 urls.py:48 django_authopenid/urls.py:29
msgid "delete/"
msgstr "borrar/"
-#: urls.py:51
+#: urls.py:50
msgid "question/"
msgstr "pregunta/"
-#: urls.py:52 urls.py:53 forum/views.py:747 forum/views.py:2071
+#: urls.py:51 urls.py:52 forum/views.py:740 forum/views.py:2013
msgid "tags/"
msgstr "etiquetas/"
-#: urls.py:54 urls.py:55 urls.py:56 forum/views.py:1034 forum/views.py:1038
-#: forum/views.py:1476 forum/views.py:1809 forum/views.py:2073
+#: urls.py:53 urls.py:54 urls.py:55 forum/views.py:993 forum/views.py:997
+#: forum/views.py:1418 forum/views.py:1751 forum/views.py:2015
msgid "users/"
msgstr "usuarios/"
-#: urls.py:57 urls.py:58
+#: urls.py:56 urls.py:57
msgid "badges/"
msgstr "distinciones/"
-#: urls.py:59
+#: urls.py:58
msgid "messages/"
msgstr "mensajes/"
-#: urls.py:59
+#: urls.py:58
msgid "markread/"
msgstr "marcarleido/"
-#: urls.py:61
+#: urls.py:60
msgid "nimda/"
msgstr "administrador/"
-#: urls.py:63
+#: urls.py:62
msgid "upload/"
msgstr "subir/"
-#: urls.py:64 urls.py:65 urls.py:66
+#: urls.py:63 urls.py:64 urls.py:65
msgid "books/"
msgstr "libros/"
-#: urls.py:67
+#: urls.py:66
msgid "search/"
msgstr "buscar/"
@@ -244,7 +240,7 @@ msgstr "la nueva contraseña no coincide"
msgid "Incorrect username."
msgstr "Nombre de usuario incorrecto"
-#: django_authopenid/urls.py:10 forum/views.py:310 forum/views.py:706
+#: django_authopenid/urls.py:10 forum/views.py:304 forum/views.py:699
msgid "newquestion/"
msgstr "nuevapregunta/"
@@ -264,19 +260,14 @@ msgstr "completado/"
msgid "register/"
msgstr "registrarse/"
-#: django_authopenid/urls.py:19
+#: django_authopenid/urls.py:16
+msgid "signup/"
+msgstr "registrarse/"
+
+#: django_authopenid/urls.py:18
msgid "sendpw/"
msgstr "enviarcontrasena/"
-#: django_authopenid/urls.py:20
-#, fuzzy
-msgid "password/"
-msgstr "contraseña"
-
-#: django_authopenid/urls.py:20
-msgid "confirm/"
-msgstr ""
-
#: django_authopenid/urls.py:27
msgid "validate/"
msgstr ""
@@ -532,8 +523,8 @@ msgstr ""
"por favor use solo los siguientes caracteres en los nombres de etiquetas: "
"letras 'a-z', números y caracteres '.-_#'"
-#: forum/forms.py:75 templates/index.html:57 templates/question.html:210
-#: templates/question.html.py:396 templates/questions.html:58
+#: forum/forms.py:75 templates/index.html:57 templates/question.html:209
+#: templates/question.html.py:395 templates/questions.html:58
#: templates/questions.html.py:70 templates/unanswered.html:48
#: templates/unanswered.html.py:60
msgid "community wiki"
@@ -559,84 +550,75 @@ msgstr ""
"ingresa un breve resumen de tu revisión (ej. error ortográfico, gramática, "
"mejoras de estilo. Este campo es opcional."
-#: forum/forms.py:98 forum/forms.py:159
-msgid "please choice a category"
-msgstr "por favor escoja una categoría"
-
-#: forum/forms.py:99 forum/forms.py:160
-msgid "Category"
-msgstr "Categoría"
-
-#: forum/forms.py:180
+#: forum/forms.py:175
msgid "this email does not have to be linked to gravatar"
msgstr "este email no tiene porque estar asociado a un Gravatar"
-#: forum/forms.py:181
+#: forum/forms.py:176
msgid "Real name"
msgstr "Nombre real"
-#: forum/forms.py:182
+#: forum/forms.py:177
msgid "Website"
msgstr "Sitio Web"
-#: forum/forms.py:183
+#: forum/forms.py:178
msgid "Location"
msgstr "Ubicación"
-#: forum/forms.py:184
+#: forum/forms.py:179
msgid "Date of birth"
msgstr "Fecha de nacimiento"
-#: forum/forms.py:184
+#: forum/forms.py:179
msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
msgstr "no será mostrado, usado para calcular la edad. Formato: YYY-MM-DD"
-#: forum/forms.py:185 templates/authopenid/settings.html:21
+#: forum/forms.py:180 templates/authopenid/settings.html:21
msgid "Profile"
msgstr "Perfil"
-#: forum/forms.py:212 forum/forms.py:213
+#: forum/forms.py:207 forum/forms.py:208
msgid "this email has already been registered, please use another one"
msgstr "este email ya ha sido registrado, por favor use otro"
-#: forum/models.py:253
-#, python-format
+#: forum/models.py:246
msgid "%(author)s modified the question"
msgstr "%(author)s modificó la pregunta"
-#: forum/models.py:257
+#: forum/models.py:250
#, python-format
msgid "%(people)s posted %(new_answer_count)s new answers"
msgstr "%(people)s publicaron %(new_answer_count)s nuevas respuestas"
-#: forum/models.py:262
+#: forum/models.py:255
#, python-format
msgid "%(people)s commented the question"
msgstr "%(people)s comentarion la pregunta"
-#: forum/models.py:267
+#: forum/models.py:260
#, python-format
msgid "%(people)s commented answers"
msgstr "%(people)s comentaron la respuesta"
-#: forum/models.py:269
+#: forum/models.py:262
#, python-format
msgid "%(people)s commented an answer"
msgstr "%(people)s comentaron la respuesta"
-#: forum/models.py:313 forum/models.py:425
+#: forum/models.py:306 forum/models.py:418
msgid "revisions"
msgstr "revisiones/"
-#: forum/models.py:448 templates/badges.html:51
+#: forum/models.py:441 templates/badges.html:51
msgid "gold"
msgstr "oro"
-#: forum/models.py:449 templates/badges.html:59
+#: forum/models.py:442 templates/badges.html:59
msgid "silver"
msgstr "plata"
-#: forum/models.py:450 templates/badges.html:66
+#: forum/models.py:443 templates/badges.html:66
msgid "bronze"
msgstr "bronce"
@@ -724,27 +706,27 @@ msgstr "preferencias del usuario"
msgid "profile - user preferences"
msgstr "perfil - preferencia de "
-#: forum/views.py:988
+#: forum/views.py:947
#, python-format
msgid "subscription saved, %(email)s needs validation"
msgstr "subscripción guardada, %(email)s necesita validación"
-#: forum/views.py:1918
+#: forum/views.py:1860
msgid "uploading images is limited to users with >60 reputation points"
msgstr "para subir imagenes debes tener más de 60 puntos de reputación"
-#: forum/views.py:1920
+#: forum/views.py:1862
msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
msgstr ""
"los tipos de archivos permitidos son 'jpg', 'jpeg', 'gif', 'bmp', 'png', "
"'tiff'"
-#: forum/views.py:1922
+#: forum/views.py:1864
#, python-format
msgid "maximum upload file size is %sK"
msgstr "tamaño máximo permitido es archivo %sK"
-#: forum/views.py:1924
+#: forum/views.py:1866
#, python-format
msgid ""
"Error uploading file. Please contact the site administrator. Thank you. %s"
@@ -868,22 +850,22 @@ msgid "select revision"
msgstr "seleccionar revisión"
#: templates/answer_edit.html:62 templates/ask.html:94
-#: templates/question.html:468 templates/question_edit.html:91
+#: templates/question.html:467 templates/question_edit.html:91
msgid "Toggle the real time Markdown editor preview"
msgstr "Activar la visualización en tiempo real de Markdown"
#: templates/answer_edit.html:62 templates/ask.html:94
-#: templates/question.html:468 templates/question_edit.html:91
+#: templates/question.html:467 templates/question_edit.html:91
msgid "toggle preview"
msgstr "Activar previsualización"
-#: templates/answer_edit.html:71 templates/question_edit.html:121
+#: templates/answer_edit.html:71 templates/question_edit.html:115
#: templates/question_retag.html:73
msgid "Save edit"
msgstr "Guardar la edición"
#: templates/answer_edit.html:72 templates/close.html:29
-#: templates/question_edit.html:122 templates/question_retag.html:74
+#: templates/question_edit.html:116 templates/question_retag.html:74
#: templates/reopen.html:30 templates/user_edit.html:83
#: templates/authopenid/changeemail.html:34
msgid "Cancel"
@@ -974,16 +956,15 @@ msgstr ""
"a>. Puedes enviar tu pregunta ahora y validar tu email luego. Tu "
"pregunta será guardada mientras tanto y publicada cuando valides tu email."
-#: templates/ask.html:107 templates/ask.html.py:114
-#: templates/question_edit.html:117
+#: templates/ask.html:107
msgid "(required)"
msgstr "(requerido)"
-#: templates/ask.html:121
+#: templates/ask.html:114
msgid "Login/signup to post your question"
msgstr "Iniciar sesión/registrarse para publicar su pregunta"
-#: templates/ask.html:123
+#: templates/ask.html:116
msgid "Ask your question"
msgstr "Haz tu pregunta"
@@ -999,7 +980,7 @@ msgstr "Usuarios han sido galardonados con distinciones:"
msgid "Badges summary"
msgstr "Resumen de distinciones"
-#: templates/badges.html:17 templates/user_stats.html:73
+#: templates/badges.html:17 templates/user_stats.html:115
msgid "Badges"
msgstr "Distinciones"
@@ -1100,17 +1081,17 @@ msgid "ask the author"
msgstr "preguntar al autor"
#: templates/book.html:88 templates/book.html.py:93
-#: templates/users_questions.html:18
+#: templates/users_questions.html:17
msgid "this question was selected as favorite"
msgstr "esta pregunta ha sido seleccionada como favorita"
#: templates/book.html:88 templates/book.html.py:93
-#: templates/users_questions.html:11 templates/users_questions.html.py:18
+#: templates/users_questions.html:11 templates/users_questions.html.py:17
msgid "number of times"
msgstr "numero de veces"
#: templates/book.html:105 templates/index.html:48 templates/questions.html:46
-#: templates/unanswered.html:37 templates/users_questions.html:32
+#: templates/unanswered.html:37 templates/users_questions.html:30
msgid "votes"
msgstr "votos"
@@ -1119,14 +1100,14 @@ msgid "the answer has been accepted to be correct"
msgstr "la respuesta ha sido aceptada como correcta"
#: templates/book.html:115 templates/index.html:49 templates/questions.html:47
-#: templates/unanswered.html:38 templates/users_questions.html:42
+#: templates/unanswered.html:38 templates/users_questions.html:40
msgid "views"
msgstr "vistas"
-#: templates/book.html:125 templates/index.html:69 templates/question.html:500
-#: templates/questions.html:84 templates/questions.html.py:157
+#: templates/book.html:125 templates/index.html:69 templates/question.html:499
+#: templates/questions.html:84 templates/questions.html.py:156
#: templates/tags.html:49 templates/unanswered.html:75
-#: templates/unanswered.html.py:106 templates/users_questions.html:54
+#: templates/unanswered.html.py:106 templates/users_questions.html:52
msgid "using tags"
msgstr "usando etiquetas"
@@ -1138,23 +1119,6 @@ msgstr "suscribirse al RSS del libro"
msgid "subscribe to the questions feed"
msgstr "suscribirse al agregado de noticias"
-#: templates/categories.html:6 templates/categories.html.py:29
-msgid "Category list"
-msgstr "Lista de Categorías"
-
-#: templates/categories.html:34 templates/tags.html:42
-msgid "Nothing found"
-msgstr "Nada encontrado"
-
-#: templates/categories.html:40
-#, fuzzy
-msgid "see questions that matches"
-msgstr "ver preguntas etiquetadas"
-
-#: templates/categories.html:40
-msgid "category "
-msgstr "categoría"
-
#: templates/close.html:6 templates/close.html.py:16
msgid "Close question"
msgstr "Cerrar pregunta"
@@ -1514,14 +1478,14 @@ msgid "all questions"
msgstr "todas las preguntas"
#: templates/index.html:47 templates/questions.html:45
-#: templates/unanswered.html:36 templates/users_questions.html:37
+#: templates/unanswered.html:36 templates/users_questions.html:35
msgid "answers"
msgstr "respuestas"
-#: templates/index.html:69 templates/question.html:500
-#: templates/questions.html:84 templates/questions.html.py:157
+#: templates/index.html:69 templates/question.html:499
+#: templates/questions.html:84 templates/questions.html.py:156
#: templates/tags.html:49 templates/unanswered.html:75
-#: templates/unanswered.html.py:106 templates/users_questions.html:54
+#: templates/unanswered.html.py:106 templates/users_questions.html:52
msgid "see questions tagged"
msgstr "ver preguntas etiquetadas"
@@ -1668,7 +1632,7 @@ msgid "i like this post (click again to cancel)"
msgstr "Me gusta esta entrada (clickear devuelta para cancelar)"
#: templates/question.html:75 templates/question.html.py:89
-#: templates/question.html:290
+#: templates/question.html:289
msgid "current number of votes"
msgstr "número actual de votos"
@@ -1687,171 +1651,169 @@ msgstr ""
"remover marca de favorito a esta pregunta (clickear devuelta para volver a "
"marcar)"
-#: templates/question.html:128 templates/questions.html:87
-msgid "Category: "
-msgstr "Categoría: "
-
-#: templates/question.html:135 templates/question.html.py:323
+#: templates/question.html:134 templates/question.html.py:322
#: templates/revisions_answer.html:53 templates/revisions_question.html:53
msgid "edit"
msgstr "editar"
-#: templates/question.html:139 templates/question.html.py:333
+#: templates/question.html:138 templates/question.html.py:332
msgid "delete"
msgstr "borrar"
-#: templates/question.html:144
+#: templates/question.html:143
msgid "reopen"
msgstr "re-abrir"
-#: templates/question.html:149
+#: templates/question.html:148
msgid "close"
msgstr "cerrar"
-#: templates/question.html:155 templates/question.html.py:346
+#: templates/question.html:154 templates/question.html.py:345
msgid ""
"report as offensive (i.e containing spam, advertising, malicious text, etc.)"
msgstr ""
"reportar como ofensivo (ej. contiene spam, publicidad, texto malicioso, etc.)"
-#: templates/question.html:156 templates/question.html.py:347
+#: templates/question.html:155 templates/question.html.py:346
msgid "flag offensive"
msgstr "marcar como ofensivo"
-#: templates/question.html:168 templates/question.html.py:356
+#: templates/question.html:167 templates/question.html.py:355
#: templates/revisions_answer.html:65 templates/revisions_question.html:65
msgid "updated"
msgstr "actualizado"
-#: templates/question.html:217 templates/question.html.py:403
+#: templates/question.html:216 templates/question.html.py:402
#: templates/revisions_answer.html:63 templates/revisions_question.html:63
msgid "asked"
msgstr "preguntado"
-#: templates/question.html:247 templates/question.html.py:430
+#: templates/question.html:246 templates/question.html.py:429
msgid "comments"
msgstr "comentarios"
-#: templates/question.html:248 templates/question.html.py:431
+#: templates/question.html:247 templates/question.html.py:430
msgid "add comment"
msgstr "agregar comentario"
-#: templates/question.html:261
-msgid "The question has been closed for the following reason"
-msgstr "La pregunta fue cerrada por el siguiente motivo "
-
-#: templates/question.html:261
-msgid "by"
-msgstr "por"
+#: templates/question.html:260
+#, python-format
+msgid ""
+"The question has been closed for the following reason \"%(question."
+"get_close_reason_display)s\" by"
+msgstr ""
+"La pregunta ha sido cerrada por el siguiente motivo \"%(question."
+"get_close_reason_display)s\" por"
-#: templates/question.html:263
-msgid "close date "
-msgstr "fecha de cierre"
+#: templates/question.html:262
+#, python-format
+msgid "close date %(question.closed_at)s"
+msgstr "fecha de cerrada %(question.closed_at)s"
-#: templates/question.html:270 templates/user_stats.html:13
+#: templates/question.html:269 templates/user_stats.html:28
msgid "Answers"
msgstr "Respuestas"
-#: templates/question.html:272
+#: templates/question.html:271
msgid "oldest answers will be shown first"
msgstr "la respuesta mas vieja será mostrada primero"
-#: templates/question.html:272
+#: templates/question.html:271
msgid "oldest answers"
msgstr "pregunta más vieja"
-#: templates/question.html:273
+#: templates/question.html:272
msgid "newest answers will be shown first"
msgstr "preguntas más nuevas serán mostradas primero"
-#: templates/question.html:273
+#: templates/question.html:272
msgid "newest answers"
msgstr "más nuevas"
-#: templates/question.html:274
+#: templates/question.html:273
msgid "most voted answers will be shown first"
msgstr "las preguntas más votadas serán mostradas primero"
-#: templates/question.html:274
+#: templates/question.html:273
msgid "popular answers"
msgstr "respuestas populares"
-#: templates/question.html:288 templates/question.html.py:289
+#: templates/question.html:287 templates/question.html.py:288
msgid "i like this answer (click again to cancel)"
msgstr "me gusta esta respuesta (clickear devuelta para cancelar)"
-#: templates/question.html:295 templates/question.html.py:296
+#: templates/question.html:294 templates/question.html.py:295
msgid "i dont like this answer (click again to cancel)"
msgstr "no me gusta esta respuesta (clickear devuelta para cancelar)"
-#: templates/question.html:301 templates/question.html.py:302
+#: templates/question.html:300 templates/question.html.py:301
msgid "mark this answer as favorite (click again to undo)"
msgstr "marcar esta respuesta como favorita (clickear devuelta para deshacer)"
-#: templates/question.html:307 templates/question.html.py:308
+#: templates/question.html:306 templates/question.html.py:307
msgid "the author of the question has selected this answer as correct"
msgstr "el autor de esta pregunta ha seleccionado esta respuesta como correcta"
-#: templates/question.html:330
+#: templates/question.html:329
msgid "undelete"
msgstr "deshacer eliminar"
-#: templates/question.html:340
+#: templates/question.html:339
msgid "answer permanent link"
msgstr "enlace permanente a respuesta"
-#: templates/question.html:341
+#: templates/question.html:340
msgid "permanent link"
msgstr "enlace permanente"
-#: templates/question.html:454
+#: templates/question.html:453
msgid "Your answer"
msgstr "Tu respuesta"
-#: templates/question.html:457
+#: templates/question.html:456
msgid "you can answer anonymously and then login"
msgstr "puedes responder de forma anónima y luego ingresar"
-#: templates/question.html:480
+#: templates/question.html:479
msgid "Answer the question"
msgstr "Responde la pregunta"
-#: templates/question.html:482
+#: templates/question.html:481
msgid "Notify me daily if there are any new answers."
msgstr "Notificarme diariamente si hay nuevas respuestas."
-#: templates/question.html:484
+#: templates/question.html:483
msgid "once you sign in you will be able to subscribe for any updates here"
msgstr ""
"una vez que hayas ingresado podrás suscribirte a cualquiera de las "
"actualizaciones aquí."
-#: templates/question.html:495
+#: templates/question.html:494
msgid "Question tags"
msgstr "Tags de la pregunta"
-#: templates/question.html:505
+#: templates/question.html:504
msgid "question asked"
msgstr "pregunta preguntada"
-#: templates/question.html:505 templates/question.html.py:511
+#: templates/question.html:504 templates/question.html.py:510
#: templates/user_info.html:51
msgid "ago"
msgstr " atras"
-#: templates/question.html:508
+#: templates/question.html:507
msgid "question was seen"
msgstr "la pregunta fue vista"
-#: templates/question.html:508
+#: templates/question.html:507
msgid "times"
msgstr "veces"
-#: templates/question.html:511
+#: templates/question.html:510
msgid "last updated"
msgstr "última vez actualizada"
-#: templates/question.html:516
+#: templates/question.html:515
msgid "Related questions"
msgstr "Preguntas relacionadas"
@@ -1916,7 +1878,7 @@ msgstr "preguntas actualizadas más recientemente"
msgid "active"
msgstr "actividad"
-#: templates/questions.html:110
+#: templates/questions.html:109
#, python-format
msgid ""
"\n"
@@ -1935,7 +1897,7 @@ msgstr[1] ""
"\t\t\ttiene un total de %(q_num)s preguntas etiquetadas con %(tagname)s\n"
"\t\t\t"
-#: templates/questions.html:117
+#: templates/questions.html:116
#, python-format
msgid ""
"\n"
@@ -1954,7 +1916,7 @@ msgstr[1] ""
"\t\t\thay un total de %(q_num)s pregunta que contiene %(searchtitle)s\n"
"\t\t\t"
-#: templates/questions.html:123
+#: templates/questions.html:122
#, fuzzy, python-format
msgid ""
"\n"
@@ -1967,36 +1929,36 @@ msgid_plural ""
msgstr[0] "ver preguntas etiquetadas '%(tagname)s'"
msgstr[1] "ver pregunta etiquetada '%(tagname)s'"
-#: templates/questions.html:132
+#: templates/questions.html:131
msgid "latest questions info"
msgstr "Más recientes preguntas son mostradas primero."
-#: templates/questions.html:136
+#: templates/questions.html:135
msgid "Questions are sorted by the time of last update."
msgstr ""
"Las preguntas estan ordenadas por fecha de último update."
-#: templates/questions.html:137
+#: templates/questions.html:136
msgid "Most recently answered ones are shown first."
msgstr "Las más recientemente respondidas son mostradas primero."
-#: templates/questions.html:141
+#: templates/questions.html:140
msgid "Questions sorted by number of responses."
msgstr "Preguntas ordenadas por número de respuestas."
-#: templates/questions.html:142
+#: templates/questions.html:141
msgid "Most answered questions are shown first."
msgstr "Preguntas más respondidas aparecen primero."
-#: templates/questions.html:146
+#: templates/questions.html:145
msgid "Questions are sorted by the number of votes."
msgstr "Las preguntas son ordenadas por el número de votos."
-#: templates/questions.html:147
+#: templates/questions.html:146
msgid "Most voted questions are shown first."
msgstr "Las preguntas más votadas son mostradas primero."
-#: templates/questions.html:154 templates/unanswered.html:102
+#: templates/questions.html:153 templates/unanswered.html:102
msgid "Related tags"
msgstr "Etiquetas relacionadas"
@@ -2061,6 +2023,10 @@ msgstr "Todas las etiquetas que coincidan con la busqueda"
msgid "all tags - make this empty in english"
msgstr "todas las tags"
+#: templates/tags.html:42
+msgid "Nothing found"
+msgstr "Nada encontrado"
+
#: templates/unanswered.html:7 templates/unanswered.html.py:18
msgid "Unanswered questions"
msgstr "Preguntas sin respuesta"
@@ -2160,50 +2126,41 @@ msgstr "Enviar mis respuestas a Twitter"
msgid "Save"
msgstr "Guardar"
-#: templates/user_stats.html:10
+#: templates/user_stats.html:16
msgid "User questions"
msgstr "Preguntas del usuario"
-#: templates/user_stats.html:20
+#: templates/user_stats.html:38
#, python-format
msgid "the answer has been voted for %(vote_count)s times"
msgstr "la respuesta ha sido votada %(vote_count)s veces"
-#: templates/user_stats.html:20
+#: templates/user_stats.html:38
msgid "this answer has been selected as correct"
msgstr "esta respuesta ha sido seleccionada como correcta"
-#: templates/user_stats.html:28
+#: templates/user_stats.html:46
#, python-format
msgid "the answer has been commented %(comment_count)s times"
msgstr "la respuesta ha sido comentada %(comment_count)s veces"
-#: templates/user_stats.html:36
-#, fuzzy
-msgid "Votes"
-msgstr "votos"
-
-#: templates/user_stats.html:41
-msgid "thumb up"
-msgstr ""
+#: templates/user_stats.html:60
+msgid "votes total"
+msgstr "votos totales"
-#: templates/user_stats.html:42
+#: templates/user_stats.html:69
msgid "user has voted up this many times"
msgstr "el usuario ha votado positivo esta cantidad de veces"
-#: templates/user_stats.html:46
-msgid "thumb down"
-msgstr ""
-
-#: templates/user_stats.html:47
+#: templates/user_stats.html:74
msgid "user voted down this many times"
msgstr "el usuario voto negativo esta cantidad de veces"
-#: templates/user_stats.html:54
+#: templates/user_stats.html:87
msgid "Tags"
msgstr "Etiquetas"
-#: templates/user_stats.html:61
+#: templates/user_stats.html:97
#, python-format
msgid "see other questions tagged '%(tag)s' "
msgstr "ver otras preguntas etiqueteadas '%(tag)s'"
@@ -2220,11 +2177,6 @@ msgstr "gráfica de la reputación del usuario"
msgid "reputation history"
msgstr "historial de reputación"
-#: templates/user_tabs.html:23
-#, fuzzy
-msgid "questions that user selected as his/her favorite"
-msgstr "esta pregunta ha sido seleccionada como favorita"
-
#: templates/user_tabs.html:24
msgid "favorites"
msgstr "favoritos"
@@ -2262,15 +2214,7 @@ msgstr "Nada encontrado."
msgid "this questions was selected as favorite"
msgstr "esta pregunta ha sido seleccionada como favorita"
-#: templates/users_questions.html:12
-msgid "thumb-up on"
-msgstr ""
-
-#: templates/users_questions.html:19
-msgid "thumb-up off"
-msgstr ""
-
-#: templates/users_questions.html:35
+#: templates/users_questions.html:33
msgid "this answer has been accepted to be correct"
msgstr "esta respuesta ha sido aceptada como correcta"
@@ -2296,7 +2240,7 @@ msgid "Your new Email"
msgstr "Tu nuevo Email"
#: templates/authopenid/changeemail.html:31
-#: templates/authopenid/signin.html:137
+#: templates/authopenid/signin.html:136
msgid "Password"
msgstr "Contraseña"
@@ -2404,7 +2348,7 @@ msgid "This account already exists, please use another."
msgstr "Esta cuenta ya existe, por favor usar otra."
#: templates/authopenid/complete.html:19 templates/authopenid/complete.html:32
-#: templates/authopenid/sendpw.html:16 templates/authopenid/signin.html:121
+#: templates/authopenid/signin.html:120
msgid "Sorry, looks like we have some errors:"
msgstr "Ups, parece que hay errores:"
@@ -2436,10 +2380,40 @@ msgstr "contraseña"
msgid "Register"
msgstr "Registrarse"
-#: templates/authopenid/complete.html:62 templates/authopenid/signin.html:139
+#: templates/authopenid/complete.html:62 templates/authopenid/signin.html:138
msgid "Forgot your password?"
msgstr "¿Olvidaste tu contraseña?"
+#: templates/authopenid/confirm_email.txt:2
+msgid "Thank you for registering at our Q&A forum!"
+msgstr ""
+
+#: templates/authopenid/confirm_email.txt:4
+msgid "Your account details are:"
+msgstr ""
+
+#: templates/authopenid/confirm_email.txt:6
+#: templates/authopenid/sendpw_email.txt:7
+msgid "Username:"
+msgstr "Nombre de usuario:"
+
+#: templates/authopenid/confirm_email.txt:7
+#: templates/authopenid/delete.html:20
+msgid "Password:"
+msgstr "Contraseña"
+
+#: templates/authopenid/confirm_email.txt:9
+msgid "Please sign in here:"
+msgstr ""
+
+#: templates/authopenid/confirm_email.txt:12
+#: templates/authopenid/email_validation.txt:14
+#: templates/authopenid/sendpw_email.txt:13
+msgid ""
+"Sincerely,\n"
+"Forum Administrator"
+msgstr ""
+
#: templates/authopenid/delete.html:9
msgid "Account: delete account"
msgstr "Cuenta: borrar cuenta"
@@ -2456,10 +2430,6 @@ msgstr ""
msgid "Check confirm box, if you want delete your account."
msgstr "Marca caja de confirmación, si deseas borrar tu cuenta."
-#: templates/authopenid/delete.html:20
-msgid "Password:"
-msgstr "Contraseña"
-
#: templates/authopenid/delete.html:32
msgid "I am sure I want to delete my account."
msgstr "Estoy seguro que quiero borrar mi cuenta."
@@ -2476,6 +2446,25 @@ msgstr "(requerido por tu seguridad)"
msgid "Delete account permanently"
msgstr "Borrar la cuenta de forma permanente"
+#: templates/authopenid/email_validation.txt:2
+msgid "Greetings from the Q&A forum"
+msgstr ""
+
+#: templates/authopenid/email_validation.txt:4
+msgid "To make use of the Forum, please follow the link below:"
+msgstr ""
+
+#: templates/authopenid/email_validation.txt:8
+msgid "Following the link above will help us verify your email address."
+msgstr ""
+
+#: templates/authopenid/email_validation.txt:10
+msgid ""
+"If you beleive that this message was sent in mistake - \n"
+"no further action is needed. Just ingore this email, we apologize\n"
+"for any inconvenience"
+msgstr ""
+
#: templates/authopenid/sendpw.html:4 templates/authopenid/sendpw.html.py:8
msgid "Send new password"
msgstr "Enviar nueva contraseña"
@@ -2512,6 +2501,26 @@ msgstr ""
"Nota: tu nueva contraseña solo será activada luego de que hagas click en el "
"link de activación en el email enviado."
+#: templates/authopenid/sendpw_email.txt:2
+#, python-format
+msgid ""
+"Someone has requested to reset your password on %(site_url)s.\n"
+"If it were not you, it is safe to ignore this email."
+msgstr ""
+
+#: templates/authopenid/sendpw_email.txt:5
+msgid "Your new account details are:"
+msgstr ""
+
+#: templates/authopenid/sendpw_email.txt:8
+#, fuzzy
+msgid "New password:"
+msgstr "Nueva contraseña:"
+
+#: templates/authopenid/sendpw_email.txt:10
+msgid "To confirm that you wanted to reset your password please visit:"
+msgstr ""
+
#: templates/authopenid/settings.html:30
msgid "Give your account a new password."
msgstr "Crea una nueva contraseña para tu cuenta."
@@ -2580,7 +2589,7 @@ msgstr ""
"Ingresa tu dirección (URL) de OpenID"
-#: templates/authopenid/signin.html:112 templates/authopenid/signin.html:138
+#: templates/authopenid/signin.html:112 templates/authopenid/signin.html:137
msgid "Login"
msgstr "Ingresar"
@@ -2588,48 +2597,48 @@ msgstr "Ingresar"
msgid "we support two login modes"
msgstr "soportamos dos tipos de ingreso"
-#: templates/authopenid/signin.html:135
+#: templates/authopenid/signin.html:134
msgid "Use login name and password"
msgstr "Nombre de usuario y contraseña"
-#: templates/authopenid/signin.html:136
+#: templates/authopenid/signin.html:135
msgid "Login name"
msgstr "Nombre de usuario"
-#: templates/authopenid/signin.html:140
+#: templates/authopenid/signin.html:139
msgid "Create new account"
msgstr "Crear cuenta nueva"
-#: templates/authopenid/signin.html:149
+#: templates/authopenid/signin.html:148
msgid "Why use OpenID?"
msgstr "¿Porqué usar OpenID?"
-#: templates/authopenid/signin.html:152
+#: templates/authopenid/signin.html:151
msgid "with openid it is easier"
msgstr "Con OpenID no necesitas crear un nuevo nombre de usuario y contraseña."
-#: templates/authopenid/signin.html:155
+#: templates/authopenid/signin.html:154
msgid "reuse openid"
msgstr ""
"Puedes de forma segura re-usar el mismo nombre de usuario para todos los "
"sitios que acepten OpenID."
-#: templates/authopenid/signin.html:158
+#: templates/authopenid/signin.html:157
msgid "openid is widely adopted"
msgstr ""
"OpenID es extensamente usado. Hay más de 160,000,000 cuentas de OpenID en "
"uso en el mundo. Mas de 10,000 sitios aceptan OpenID."
-#: templates/authopenid/signin.html:161
+#: templates/authopenid/signin.html:160
msgid "openid is supported open standard"
msgstr ""
"OpenID es basado en un standard abierto, apoyado por muchas organizaciones."
-#: templates/authopenid/signin.html:166
+#: templates/authopenid/signin.html:165
msgid "Find out more"
msgstr "Averigua más"
-#: templates/authopenid/signin.html:167
+#: templates/authopenid/signin.html:166
msgid "Get OpenID"
msgstr "Adquiere una OpenID"
@@ -2673,20 +2682,6 @@ msgstr "Registrate con tu OpenID"
msgid "Login with your OpenID"
msgstr "Ingresar con tu OpenID"
-#, fuzzy
-#~ msgid "complete list of quesionts"
-#~ msgstr "lista completa de preguntas"
-
-#~ msgid "votes total"
-#~ msgstr "votos totales"
-
-#~ msgid "Username:"
-#~ msgstr "Nombre de usuario:"
-
-#, fuzzy
-#~ msgid "New password:"
-#~ msgstr "Nueva contraseña:"
-
#~ msgid "site title"
#~ msgstr "Preguntalo.com.uy"
diff --git a/middleware/anon_user.py b/middleware/anon_user.py
new file mode 100644
index 00000000..c7ff05bc
--- /dev/null
+++ b/middleware/anon_user.py
@@ -0,0 +1,26 @@
+from django.http import HttpResponseRedirect
+from django_authopenid.util import get_next_url
+from user_messages import create_message, get_and_delete_messages
+import logging
+
+class AnonymousMessageManager(object):
+ def __init__(self,request):
+ self.request = request
+ def create(self,message=''):
+ create_message(self.request,message)
+ def get_and_delete(self):
+ messages = get_and_delete_messages(self.request)
+ return messages
+
+def dummy_deepcopy(*arg):
+ """this is necessary to prevent deepcopy() on anonymous user object
+ that now contains reference to request, which cannot be deepcopied
+ """
+ return None
+
+class ConnectToSessionMessagesMiddleware(object):
+ def process_request(self, request):
+ if not request.user.is_authenticated():
+ request.user.__deepcopy__ = dummy_deepcopy #plug on deepcopy which may be called by django db "driver"
+ request.user.message_set = AnonymousMessageManager(request) #here request is linked to anon user
+ request.user.get_and_delete_messages = request.user.message_set.get_and_delete
diff --git a/middleware/cancel.py b/middleware/cancel.py
new file mode 100644
index 00000000..f03ff35e
--- /dev/null
+++ b/middleware/cancel.py
@@ -0,0 +1,15 @@
+from django.http import HttpResponseRedirect
+from django_authopenid.util import get_next_url
+import logging
+class CancelActionMiddleware(object):
+ def process_view(self, request, view_func, view_args, view_kwargs):
+ if 'cancel' in request.REQUEST:
+ #todo use session messages for the anonymous users
+ try:
+ msg = getattr(view_func,'CANCEL_MESSAGE')
+ except AttributeError:
+ msg = 'action canceled'
+ request.user.message_set.create(message=msg)
+ return HttpResponseRedirect(get_next_url(request))
+ else:
+ return None
diff --git a/middleware/pagesize.py b/middleware/pagesize.py
index bb6c7aa3..f6e6fcfd 100644
--- a/middleware/pagesize.py
+++ b/middleware/pagesize.py
@@ -26,4 +26,8 @@ class QuestionsPageSizeMiddleware(object):
user.questions_per_page = pagesize
user.save()
# put pagesize into session
- request.session["pagesize"] = pagesize
\ No newline at end of file
+ request.session["pagesize"] = pagesize
+
+ def process_exception(self,request,exception):
+ import logging
+ logging.debug('have exception %s' % str(exception))
diff --git a/migration b/migration
new file mode 100644
index 00000000..eb5dffa1
--- /dev/null
+++ b/migration
@@ -0,0 +1,7 @@
+cp cnprog-current/templates/content/style/style.css test/templates/content/style/
+cp cnprog-current/templates/footer.html test/templates/
+cp cnprog-current/templates/content/images/logo.png test/templates/content/images
+cp cnprog-current/locale/en/LC_MESSAGES/django.po test/locale/en/LC_MESSAGES/
+python manage.py makemessages -l en -e html,py,txt
+#fix fuzzy messages
+python manage.py compilemessages
diff --git a/session_messages/.svn/all-wcprops b/session_messages/.svn/all-wcprops
new file mode 100644
index 00000000..2a15b353
--- /dev/null
+++ b/session_messages/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 38
+/svn/!svn/ver/5/trunk/session_messages
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 50
+/svn/!svn/ver/5/trunk/session_messages/__init__.py
+END
+models.py
+K 25
+svn:wc:ra_dav:version-url
+V 48
+/svn/!svn/ver/2/trunk/session_messages/models.py
+END
+context_processors.py
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/!svn/ver/2/trunk/session_messages/context_processors.py
+END
diff --git a/session_messages/.svn/dir-prop-base b/session_messages/.svn/dir-prop-base
new file mode 100644
index 00000000..4cc643b7
--- /dev/null
+++ b/session_messages/.svn/dir-prop-base
@@ -0,0 +1,6 @@
+K 10
+svn:ignore
+V 6
+*.pyc
+
+END
diff --git a/session_messages/.svn/entries b/session_messages/.svn/entries
new file mode 100644
index 00000000..67c0db8a
--- /dev/null
+++ b/session_messages/.svn/entries
@@ -0,0 +1,64 @@
+8
+
+dir
+5
+http://django-session-messages.googlecode.com/svn/trunk/session_messages
+http://django-session-messages.googlecode.com/svn
+
+
+
+2009-03-10T23:30:03.043791Z
+5
+carl.j.meyer
+has-props
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+b8288d2d-7354-0410-af5b-714f73743f4b
+
+__init__.py
+file
+
+
+
+
+2009-10-25T23:36:02.000000Z
+89aa0f71c9973e4889e5fad0b4771a34
+2009-03-10T23:30:03.043791Z
+5
+carl.j.meyer
+
+models.py
+file
+
+
+
+
+2009-10-25T23:36:02.000000Z
+c5b4f274dbb06bc66a14f0c18c9115cd
+2008-08-14T23:13:23.180432Z
+2
+carl.j.meyer
+
+context_processors.py
+file
+
+
+
+
+2009-10-25T23:36:02.000000Z
+24779c7e504d3f7f1918fdf3fe8096bc
+2008-08-14T23:13:23.180432Z
+2
+carl.j.meyer
+
diff --git a/session_messages/.svn/format b/session_messages/.svn/format
new file mode 100644
index 00000000..45a4fb75
--- /dev/null
+++ b/session_messages/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/session_messages/.svn/text-base/__init__.py.svn-base b/session_messages/.svn/text-base/__init__.py.svn-base
new file mode 100644
index 00000000..0136c888
--- /dev/null
+++ b/session_messages/.svn/text-base/__init__.py.svn-base
@@ -0,0 +1,36 @@
+"""
+Lightweight session-based messaging system.
+
+Time-stamp: <2009-03-10 19:22:29 carljm __init__.py>
+
+"""
+VERSION = (0, 1, 'pre')
+
+def create_message (request, message):
+ """
+ Create a message in the current session.
+
+ """
+ assert hasattr(request, 'session'), "django-session-messages requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
+
+ try:
+ request.session['messages'].append(message)
+ except KeyError:
+ request.session['messages'] = [message]
+
+def get_and_delete_messages (request, include_auth=False):
+ """
+ Get and delete all messages for current session.
+
+ Optionally also fetches user messages from django.contrib.auth.
+
+ """
+ assert hasattr(request, 'session'), "django-session-messages requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
+
+ messages = request.session.pop('messages', [])
+
+ if include_auth and request.user.is_authenticated():
+ messages.extend(request.user.get_and_delete_messages())
+
+ return messages
+
diff --git a/session_messages/.svn/text-base/context_processors.py.svn-base b/session_messages/.svn/text-base/context_processors.py.svn-base
new file mode 100644
index 00000000..df9840fd
--- /dev/null
+++ b/session_messages/.svn/text-base/context_processors.py.svn-base
@@ -0,0 +1,48 @@
+"""
+Context processor for lightweight session messages.
+
+Time-stamp: <2008-07-19 23:16:19 carljm context_processors.py>
+
+"""
+from django.utils.encoding import StrAndUnicode
+
+from session_messages import get_and_delete_messages
+
+def session_messages (request):
+ """
+ Returns session messages for the current session.
+
+ """
+ return { 'session_messages': LazyMessages(request) }
+
+class LazyMessages (StrAndUnicode):
+ """
+ Lazy message container, so messages aren't actually retrieved from
+ session and deleted until the template asks for them.
+
+ """
+ def __init__(self, request):
+ self.request = request
+
+ def __iter__(self):
+ return iter(self.messages)
+
+ def __len__(self):
+ return len(self.messages)
+
+ def __nonzero__(self):
+ return bool(self.messages)
+
+ def __unicode__(self):
+ return unicode(self.messages)
+
+ def __getitem__(self, *args, **kwargs):
+ return self.messages.__getitem__(*args, **kwargs)
+
+ def _get_messages(self):
+ if hasattr(self, '_messages'):
+ return self._messages
+ self._messages = get_and_delete_messages(self.request)
+ return self._messages
+ messages = property(_get_messages)
+
diff --git a/session_messages/.svn/text-base/models.py.svn-base b/session_messages/.svn/text-base/models.py.svn-base
new file mode 100644
index 00000000..b67ead6d
--- /dev/null
+++ b/session_messages/.svn/text-base/models.py.svn-base
@@ -0,0 +1,3 @@
+"""
+blank models.py
+"""
diff --git a/session_messages/__init__.py b/session_messages/__init__.py
new file mode 100644
index 00000000..4dd10a6b
--- /dev/null
+++ b/session_messages/__init__.py
@@ -0,0 +1,37 @@
+"""
+Lightweight session-based messaging system.
+
+Time-stamp: <2009-03-10 19:22:29 carljm __init__.py>
+
+"""
+VERSION = (0, 1, 'pre')
+
+def create_message (request, message):
+ """
+ Create a message in the current session.
+
+ """
+ assert hasattr(request, 'session'), "django-session-messages requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
+
+ try:
+ request.session['messages'].append(message)
+ except KeyError:
+ request.session['messages'] = [message]
+
+def get_and_delete_messages (request, include_auth=False):
+ """
+ Get and delete all messages for current session.
+
+ Optionally also fetches user messages from django.contrib.auth.
+
+ """
+ assert hasattr(request, 'session'), "django-session-messages requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
+
+ messages = request.session.pop('messages', [])
+ import logging
+
+ if include_auth and request.user.is_authenticated():
+ messages.extend(request.user.get_and_delete_messages())
+
+ return messages
+
diff --git a/session_messages/context_processors.py b/session_messages/context_processors.py
new file mode 100644
index 00000000..df9840fd
--- /dev/null
+++ b/session_messages/context_processors.py
@@ -0,0 +1,48 @@
+"""
+Context processor for lightweight session messages.
+
+Time-stamp: <2008-07-19 23:16:19 carljm context_processors.py>
+
+"""
+from django.utils.encoding import StrAndUnicode
+
+from session_messages import get_and_delete_messages
+
+def session_messages (request):
+ """
+ Returns session messages for the current session.
+
+ """
+ return { 'session_messages': LazyMessages(request) }
+
+class LazyMessages (StrAndUnicode):
+ """
+ Lazy message container, so messages aren't actually retrieved from
+ session and deleted until the template asks for them.
+
+ """
+ def __init__(self, request):
+ self.request = request
+
+ def __iter__(self):
+ return iter(self.messages)
+
+ def __len__(self):
+ return len(self.messages)
+
+ def __nonzero__(self):
+ return bool(self.messages)
+
+ def __unicode__(self):
+ return unicode(self.messages)
+
+ def __getitem__(self, *args, **kwargs):
+ return self.messages.__getitem__(*args, **kwargs)
+
+ def _get_messages(self):
+ if hasattr(self, '_messages'):
+ return self._messages
+ self._messages = get_and_delete_messages(self.request)
+ return self._messages
+ messages = property(_get_messages)
+
diff --git a/session_messages/models.py b/session_messages/models.py
new file mode 100644
index 00000000..b67ead6d
--- /dev/null
+++ b/session_messages/models.py
@@ -0,0 +1,3 @@
+"""
+blank models.py
+"""
diff --git a/settings.py b/settings.py
index fcfdb548..daada933 100644
--- a/settings.py
+++ b/settings.py
@@ -1,25 +1,23 @@
# encoding:utf-8
# Django settings for lanai project.
import os.path
+import sys
+sys.path.insert(0,'/home/fadeev/incoming/Django-1.1.1')
#DEBUG SETTINGS
-DEBUG = True
+DEBUG = False
TEMPLATE_DEBUG = DEBUG
-INTERNAL_IPS = ('127.0.0.1',)
-
-#for OpenID auth
-ugettext = lambda s: s
-LOGIN_URL = '/%s%s' % (ugettext('account/'), ugettext('signin/'))
+INTERNAL_IPS = ('127.0.0.1','128.200.203.33')
#EMAIL AND ADMINS
ADMINS = (
- ('CNProg team', 'team@cnprog.com'),
+ ('Evgeny Fadeev', 'evgeny.fadeev@gmail.com'),
)
MANAGERS = ADMINS
SITE_ID = 1
-ADMIN_MEDIA_PREFIX = '/admin/media/'
+ADMIN_MEDIA_PREFIX = '/forum/admin/media/'
SECRET_KEY = '$oo^&_m&qwbib=(_4m_n*zn-d=g#s0he5fx9xonnym#8p6yigm'
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
@@ -36,16 +34,18 @@ MIDDLEWARE_CLASSES = (
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.transaction.TransactionMiddleware',
#'django.middleware.sqlprint.SqlPrintingMiddleware',
- #'middleware.pagesize.QuestionsPageSizeMiddleware',
+ 'middleware.anon_user.ConnectToSessionMessagesMiddleware',
+ 'middleware.pagesize.QuestionsPageSizeMiddleware',
+ 'middleware.cancel.CancelActionMiddleware',
#'debug_toolbar.middleware.DebugToolbarMiddleware',
)
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
- 'context.auth_processor',
'context.application_settings',
#'django.core.context_processors.i18n',
- 'django.core.context_processors.auth' #this is required for admin
+ 'user_messages.context_processors.user_messages',#must be before auth
+ 'django.core.context_processors.auth', #this is required for admin
)
ROOT_URLCONF = 'urls'
@@ -73,7 +73,8 @@ INSTALLED_APPS = (
'django.contrib.humanize',
'forum',
'django_authopenid',
- 'debug_toolbar' ,
+ #'debug_toolbar' ,
+ 'user_messages',
)
# User settings
diff --git a/settings_local.py.dist b/settings_local.py.dist
index 48d7b567..e43522ef 100644
--- a/settings_local.py.dist
+++ b/settings_local.py.dist
@@ -1,5 +1,6 @@
# encoding:utf-8
import os.path
+from django.utils.translation import ugettext as _
SITE_SRC_ROOT = os.path.dirname(__file__)
LOG_FILENAME = 'django.lanai.log'
@@ -8,40 +9,60 @@ LOG_FILENAME = 'django.lanai.log'
import logging
logging.basicConfig(filename=os.path.join(SITE_SRC_ROOT, 'log', LOG_FILENAME), level=logging.DEBUG,)
-DATABASE_NAME = '' # Or path to database file if using sqlite3.
+DATABASE_NAME = 'cnprog' # Or path to database file if using sqlite3.
DATABASE_USER = '' # Not used with sqlite3.
DATABASE_PASSWORD = '' # Not used with sqlite3.
-DATABASE_ENGINE = '' #mysql, etc
+DATABASE_ENGINE = 'mysql' #mysql, etc
#Moved from settings.py for better organization. (please check it up to clean up settings.py)
#email server settings
SERVER_EMAIL = ''
-DEFAULT_FROM_EMAIL = 'team@cnprog.com'
+DEFAULT_FROM_EMAIL = ''
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
-EMAIL_SUBJECT_PREFIX = '[cnprog.com]'
-EMAIL_HOST='smtp.gmail.com'
-EMAIL_PORT='587'
-EMAIL_USE_TLS=True
+EMAIL_SUBJECT_PREFIX = '[CNPROG] '
+EMAIL_HOST='cnprog.com'
+EMAIL_PORT='25'
+EMAIL_USE_TLS=False
#LOCALIZATIONS
-TIME_ZONE = 'Asia/Chongqing Asia/Chungking'
-# LANGUAGE_CODE = 'en-us'
+TIME_ZONE = 'America/Tijuana'
#OTHER SETTINGS
-APP_TITLE = u'CNProg.com 程序员问答社区'
-APP_KEYWORDS = u'技术问答社区,中国程序员,编程技术社区,程序员社区,程序员论坛,程序员wiki,程序员博客'
-APP_DESCRIPTION = u'中国程序员的编程技术问答社区。我们做专业的、可协作编辑的技术问答社区。'
-APP_INTRO = u'
'
+APP_COPYRIGHT = 'Copyright CNPROG, 2009. Some rights reserved under creative commons license.'
+
+###########################
+#
+# this will allow running your forum with url like http://site.com/forum
+#
+# FORUM_SCRIPT_ALIAS = 'forum/'
+#
+# also make sure to set '/':'/forum' in file templates/content/js/com.cnprog.i18n.js
+# this is necessary to make client scripts work in this configuration
+#
+FORUM_SCRIPT_ALIAS = '' #no leading slash, default = '' empty string
USE_I18N = True
LANGUAGE_CODE = 'en'
-EMAIL_VALIDATION = 'off'
+EMAIL_VALIDATION = 'off' #string - on|off
MIN_USERNAME_LENGTH = 1
EMAIL_UNIQUE = False
-APP_URL = 'http://server.com' #used by email notif system and RSS
+APP_URL = 'http://cnprog.com' #used by email notif system and RSS
GOOGLE_SITEMAP_CODE = '55uGNnQVJW8p1bbXeF/Xbh9I7nZBM/wLhRz6N/I1kkA='
GOOGLE_ANALYTICS_KEY = ''
-BOOKS_ON = True
+BOOKS_ON = False
+WIKI_ON = True
+USE_EXTERNAL_LEGACY_LOGIN = True
+EXTERNAL_LEGACY_LOGIN_HOST = 'login.cnprog.com'
+EXTERNAL_LEGACY_LOGIN_PORT = 80
+EXTERNAL_LEGACY_LOGIN_PROVIDER_NAME = 'CNPROG'
+FEEDBACK_SITE_URL = None #None or url
+LOGIN_URL = '/%s%s%s' % (FORUM_SCRIPT_ALIAS,'account/','signin/')
+
+DJANGO_VERSION = 1.1
+RESOURCE_REVISION=4
diff --git a/sql_scripts/091111_upgrade_evgeny.sql b/sql_scripts/091111_upgrade_evgeny.sql
new file mode 100644
index 00000000..cb76ec3c
--- /dev/null
+++ b/sql_scripts/091111_upgrade_evgeny.sql
@@ -0,0 +1 @@
+ALTER TABLE `auth_user` add column is_approved tinyint(1) not NULL;
diff --git a/tables.sql b/tables.sql
new file mode 100644
index 00000000..6034c08c
--- /dev/null
+++ b/tables.sql
@@ -0,0 +1,440 @@
+BEGIN;
+CREATE TABLE `forum_emailfeedsetting` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `subscriber_id` integer NOT NULL,
+ `feed_type` varchar(16) NOT NULL,
+ `frequency` varchar(8) NOT NULL,
+ `added_at` datetime NOT NULL,
+ `reported_at` datetime NULL
+)
+;
+ALTER TABLE `forum_emailfeedsetting` ADD CONSTRAINT subscriber_id_refs_id_6fee6730cc813af8 FOREIGN KEY (`subscriber_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `tag` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `name` varchar(255) NOT NULL UNIQUE,
+ `created_by_id` integer NOT NULL,
+ `deleted` bool NOT NULL,
+ `deleted_at` datetime NULL,
+ `deleted_by_id` integer NULL,
+ `used_count` integer UNSIGNED NOT NULL
+)
+;
+ALTER TABLE `tag` ADD CONSTRAINT created_by_id_refs_id_6ae4d97547205d6d FOREIGN KEY (`created_by_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `tag` ADD CONSTRAINT deleted_by_id_refs_id_6ae4d97547205d6d FOREIGN KEY (`deleted_by_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `comment` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `content_type_id` integer NOT NULL,
+ `object_id` integer UNSIGNED NOT NULL,
+ `user_id` integer NOT NULL,
+ `comment` varchar(300) NOT NULL,
+ `added_at` datetime NOT NULL
+)
+;
+ALTER TABLE `comment` ADD CONSTRAINT content_type_id_refs_id_89a4b13ec5a7994 FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`);
+ALTER TABLE `comment` ADD CONSTRAINT user_id_refs_id_5ba842626be725e8 FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `vote` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `content_type_id` integer NOT NULL,
+ `object_id` integer UNSIGNED NOT NULL,
+ `user_id` integer NOT NULL,
+ `vote` smallint NOT NULL,
+ `voted_at` datetime NOT NULL,
+ UNIQUE (`content_type_id`, `object_id`, `user_id`)
+)
+;
+ALTER TABLE `vote` ADD CONSTRAINT content_type_id_refs_id_77dc6ffafedbbec FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`);
+ALTER TABLE `vote` ADD CONSTRAINT user_id_refs_id_3ce5b20589f5b210 FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `flagged_item` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `content_type_id` integer NOT NULL,
+ `object_id` integer UNSIGNED NOT NULL,
+ `user_id` integer NOT NULL,
+ `flagged_at` datetime NOT NULL,
+ UNIQUE (`content_type_id`, `object_id`, `user_id`)
+)
+;
+ALTER TABLE `flagged_item` ADD CONSTRAINT content_type_id_refs_id_261d26c8891bb28c FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`);
+ALTER TABLE `flagged_item` ADD CONSTRAINT user_id_refs_id_92ae9d35e3c608 FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `question` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `title` varchar(300) NOT NULL,
+ `author_id` integer NOT NULL,
+ `added_at` datetime NOT NULL,
+ `wiki` bool NOT NULL,
+ `wikified_at` datetime NULL,
+ `answer_accepted` bool NOT NULL,
+ `closed` bool NOT NULL,
+ `closed_by_id` integer NULL,
+ `closed_at` datetime NULL,
+ `close_reason` smallint NULL,
+ `deleted` bool NOT NULL,
+ `deleted_at` datetime NULL,
+ `deleted_by_id` integer NULL,
+ `locked` bool NOT NULL,
+ `locked_by_id` integer NULL,
+ `locked_at` datetime NULL,
+ `score` integer NOT NULL,
+ `vote_up_count` integer NOT NULL,
+ `vote_down_count` integer NOT NULL,
+ `answer_count` integer UNSIGNED NOT NULL,
+ `comment_count` integer UNSIGNED NOT NULL,
+ `view_count` integer UNSIGNED NOT NULL,
+ `offensive_flag_count` smallint NOT NULL,
+ `favourite_count` integer UNSIGNED NOT NULL,
+ `last_edited_at` datetime NULL,
+ `last_edited_by_id` integer NULL,
+ `last_activity_at` datetime NOT NULL,
+ `last_activity_by_id` integer NOT NULL,
+ `tagnames` varchar(125) NOT NULL,
+ `summary` varchar(180) NOT NULL,
+ `html` longtext NOT NULL
+)
+;
+ALTER TABLE `question` ADD CONSTRAINT author_id_refs_id_5159d9f3a9162ff4 FOREIGN KEY (`author_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `question` ADD CONSTRAINT closed_by_id_refs_id_5159d9f3a9162ff4 FOREIGN KEY (`closed_by_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `question` ADD CONSTRAINT deleted_by_id_refs_id_5159d9f3a9162ff4 FOREIGN KEY (`deleted_by_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `question` ADD CONSTRAINT locked_by_id_refs_id_5159d9f3a9162ff4 FOREIGN KEY (`locked_by_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `question` ADD CONSTRAINT last_edited_by_id_refs_id_5159d9f3a9162ff4 FOREIGN KEY (`last_edited_by_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `question` ADD CONSTRAINT last_activity_by_id_refs_id_5159d9f3a9162ff4 FOREIGN KEY (`last_activity_by_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `forum_questionview` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `question_id` integer NOT NULL,
+ `who_id` integer NOT NULL,
+ `when` datetime NOT NULL
+)
+;
+ALTER TABLE `forum_questionview` ADD CONSTRAINT question_id_refs_id_fe63ebce6b3cbac FOREIGN KEY (`question_id`) REFERENCES `question` (`id`);
+ALTER TABLE `forum_questionview` ADD CONSTRAINT who_id_refs_id_293b67239e957c53 FOREIGN KEY (`who_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `favorite_question` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `question_id` integer NOT NULL,
+ `user_id` integer NOT NULL,
+ `added_at` datetime NOT NULL
+)
+;
+ALTER TABLE `favorite_question` ADD CONSTRAINT question_id_refs_id_2cafd2f21ebe1cc3 FOREIGN KEY (`question_id`) REFERENCES `question` (`id`);
+ALTER TABLE `favorite_question` ADD CONSTRAINT user_id_refs_id_1632ce11ad7ac7de FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `question_revision` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `question_id` integer NOT NULL,
+ `revision` integer UNSIGNED NOT NULL,
+ `title` varchar(300) NOT NULL,
+ `author_id` integer NOT NULL,
+ `revised_at` datetime NOT NULL,
+ `tagnames` varchar(125) NOT NULL,
+ `summary` varchar(300) NOT NULL,
+ `text` longtext NOT NULL
+)
+;
+ALTER TABLE `question_revision` ADD CONSTRAINT question_id_refs_id_61316ec87bef5296 FOREIGN KEY (`question_id`) REFERENCES `question` (`id`);
+ALTER TABLE `question_revision` ADD CONSTRAINT author_id_refs_id_79de7cc0b077fdb1 FOREIGN KEY (`author_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `forum_anonymousanswer` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `question_id` integer NOT NULL,
+ `session_key` varchar(40) NOT NULL,
+ `wiki` bool NOT NULL,
+ `added_at` datetime NOT NULL,
+ `ip_addr` char(15) NOT NULL,
+ `author_id` integer NULL,
+ `text` longtext NOT NULL,
+ `summary` varchar(180) NOT NULL
+)
+;
+ALTER TABLE `forum_anonymousanswer` ADD CONSTRAINT question_id_refs_id_17dd6b2f4cc171c7 FOREIGN KEY (`question_id`) REFERENCES `question` (`id`);
+ALTER TABLE `forum_anonymousanswer` ADD CONSTRAINT author_id_refs_id_3ac41be013fb542e FOREIGN KEY (`author_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `forum_anonymousquestion` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `title` varchar(300) NOT NULL,
+ `session_key` varchar(40) NOT NULL,
+ `text` longtext NOT NULL,
+ `summary` varchar(180) NOT NULL,
+ `tagnames` varchar(125) NOT NULL,
+ `wiki` bool NOT NULL,
+ `added_at` datetime NOT NULL,
+ `ip_addr` char(15) NOT NULL,
+ `author_id` integer NULL
+)
+;
+ALTER TABLE `forum_anonymousquestion` ADD CONSTRAINT author_id_refs_id_2a673297511a98a FOREIGN KEY (`author_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `answer` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `question_id` integer NOT NULL,
+ `author_id` integer NOT NULL,
+ `added_at` datetime NOT NULL,
+ `wiki` bool NOT NULL,
+ `wikified_at` datetime NULL,
+ `accepted` bool NOT NULL,
+ `accepted_at` datetime NULL,
+ `deleted` bool NOT NULL,
+ `deleted_by_id` integer NULL,
+ `locked` bool NOT NULL,
+ `locked_by_id` integer NULL,
+ `locked_at` datetime NULL,
+ `score` integer NOT NULL,
+ `vote_up_count` integer NOT NULL,
+ `vote_down_count` integer NOT NULL,
+ `comment_count` integer UNSIGNED NOT NULL,
+ `offensive_flag_count` smallint NOT NULL,
+ `last_edited_at` datetime NULL,
+ `last_edited_by_id` integer NULL,
+ `html` longtext NOT NULL
+)
+;
+ALTER TABLE `answer` ADD CONSTRAINT question_id_refs_id_2300e0297d6550c9 FOREIGN KEY (`question_id`) REFERENCES `question` (`id`);
+ALTER TABLE `answer` ADD CONSTRAINT author_id_refs_id_6573e62f192b0170 FOREIGN KEY (`author_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `answer` ADD CONSTRAINT deleted_by_id_refs_id_6573e62f192b0170 FOREIGN KEY (`deleted_by_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `answer` ADD CONSTRAINT locked_by_id_refs_id_6573e62f192b0170 FOREIGN KEY (`locked_by_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `answer` ADD CONSTRAINT last_edited_by_id_refs_id_6573e62f192b0170 FOREIGN KEY (`last_edited_by_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `answer_revision` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `answer_id` integer NOT NULL,
+ `revision` integer UNSIGNED NOT NULL,
+ `author_id` integer NOT NULL,
+ `revised_at` datetime NOT NULL,
+ `summary` varchar(300) NOT NULL,
+ `text` longtext NOT NULL
+)
+;
+ALTER TABLE `answer_revision` ADD CONSTRAINT answer_id_refs_id_47145eaebe77d8fe FOREIGN KEY (`answer_id`) REFERENCES `answer` (`id`);
+ALTER TABLE `answer_revision` ADD CONSTRAINT author_id_refs_id_2c17693c3ccc055f FOREIGN KEY (`author_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `badge` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `name` varchar(50) NOT NULL,
+ `type` smallint NOT NULL,
+ `slug` varchar(50) NOT NULL,
+ `description` varchar(300) NOT NULL,
+ `multiple` bool NOT NULL,
+ `awarded_count` integer UNSIGNED NOT NULL,
+ UNIQUE (`name`, `type`)
+)
+;
+CREATE TABLE `award` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL,
+ `badge_id` integer NOT NULL,
+ `content_type_id` integer NOT NULL,
+ `object_id` integer UNSIGNED NOT NULL,
+ `awarded_at` datetime NOT NULL,
+ `notified` bool NOT NULL
+)
+;
+ALTER TABLE `award` ADD CONSTRAINT user_id_refs_id_5d197ea32d83e9b6 FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `award` ADD CONSTRAINT badge_id_refs_id_4237a025651af0e1 FOREIGN KEY (`badge_id`) REFERENCES `badge` (`id`);
+ALTER TABLE `award` ADD CONSTRAINT content_type_id_refs_id_72f17e2d83bbde26 FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`);
+CREATE TABLE `repute` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL,
+ `positive` smallint NOT NULL,
+ `negative` smallint NOT NULL,
+ `question_id` integer NOT NULL,
+ `reputed_at` datetime NOT NULL,
+ `reputation_type` smallint NOT NULL,
+ `reputation` integer NOT NULL
+)
+;
+ALTER TABLE `repute` ADD CONSTRAINT user_id_refs_id_fcf719405a426cd FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `repute` ADD CONSTRAINT question_id_refs_id_4749166abeb39c4e FOREIGN KEY (`question_id`) REFERENCES `question` (`id`);
+CREATE TABLE `activity` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL,
+ `activity_type` smallint NOT NULL,
+ `active_at` datetime NOT NULL,
+ `content_type_id` integer NOT NULL,
+ `object_id` integer UNSIGNED NOT NULL,
+ `is_auditted` bool NOT NULL
+)
+;
+ALTER TABLE `activity` ADD CONSTRAINT user_id_refs_id_6015206347c8583f FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `activity` ADD CONSTRAINT content_type_id_refs_id_78877d15efa8edfd FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`);
+CREATE TABLE `book` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL,
+ `title` varchar(255) NOT NULL,
+ `short_name` varchar(255) NOT NULL,
+ `author` varchar(255) NOT NULL,
+ `price` numeric(6, 2) NOT NULL,
+ `pages` smallint NOT NULL,
+ `published_at` datetime NOT NULL,
+ `publication` varchar(255) NOT NULL,
+ `cover_img` varchar(255) NOT NULL,
+ `tagnames` varchar(125) NOT NULL,
+ `added_at` datetime NOT NULL,
+ `last_edited_at` datetime NOT NULL
+)
+;
+ALTER TABLE `book` ADD CONSTRAINT user_id_refs_id_607b4cfdf0283c8d FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `book_author_info` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL,
+ `book_id` integer NOT NULL,
+ `blog_url` varchar(255) NOT NULL,
+ `added_at` datetime NOT NULL,
+ `last_edited_at` datetime NOT NULL
+)
+;
+ALTER TABLE `book_author_info` ADD CONSTRAINT user_id_refs_id_3781e2a5fbe1cfda FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `book_author_info` ADD CONSTRAINT book_id_refs_id_688c8f047c49bbf8 FOREIGN KEY (`book_id`) REFERENCES `book` (`id`);
+CREATE TABLE `book_author_rss` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL,
+ `book_id` integer NOT NULL,
+ `title` varchar(255) NOT NULL,
+ `url` varchar(255) NOT NULL,
+ `rss_created_at` datetime NOT NULL,
+ `added_at` datetime NOT NULL
+)
+;
+ALTER TABLE `book_author_rss` ADD CONSTRAINT user_id_refs_id_1fd25dcf3596f741 FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `book_author_rss` ADD CONSTRAINT book_id_refs_id_f64066171717121 FOREIGN KEY (`book_id`) REFERENCES `book` (`id`);
+CREATE TABLE `forum_anonymousemail` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `key` varchar(32) NOT NULL,
+ `email` varchar(75) NOT NULL UNIQUE,
+ `isvalid` bool NOT NULL
+)
+;
+CREATE TABLE `question_tags` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `question_id` integer NOT NULL,
+ `tag_id` integer NOT NULL,
+ UNIQUE (`question_id`, `tag_id`)
+)
+;
+ALTER TABLE `question_tags` ADD CONSTRAINT question_id_refs_id_35d758e3d99eb83a FOREIGN KEY (`question_id`) REFERENCES `question` (`id`);
+ALTER TABLE `question_tags` ADD CONSTRAINT tag_id_refs_id_3b0ddddfbc0346ad FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`);
+CREATE TABLE `question_followed_by` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `question_id` integer NOT NULL,
+ `user_id` integer NOT NULL,
+ UNIQUE (`question_id`, `user_id`)
+)
+;
+ALTER TABLE `question_followed_by` ADD CONSTRAINT question_id_refs_id_6ea9c52125c22aae FOREIGN KEY (`question_id`) REFERENCES `question` (`id`);
+ALTER TABLE `question_followed_by` ADD CONSTRAINT user_id_refs_id_49cca2976d30712d FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `book_question` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `book_id` integer NOT NULL,
+ `question_id` integer NOT NULL,
+ UNIQUE (`book_id`, `question_id`)
+)
+;
+ALTER TABLE `book_question` ADD CONSTRAINT book_id_refs_id_535ac8946a43c4d1 FOREIGN KEY (`book_id`) REFERENCES `book` (`id`);
+ALTER TABLE `book_question` ADD CONSTRAINT question_id_refs_id_372b7e81c7aff6d8 FOREIGN KEY (`question_id`) REFERENCES `question` (`id`);
+CREATE TABLE `django_authopenid_nonce` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `server_url` varchar(255) NOT NULL,
+ `timestamp` integer NOT NULL,
+ `salt` varchar(40) NOT NULL
+)
+;
+CREATE TABLE `django_authopenid_association` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `server_url` longtext NOT NULL,
+ `handle` varchar(255) NOT NULL,
+ `secret` longtext NOT NULL,
+ `issued` integer NOT NULL,
+ `lifetime` integer NOT NULL,
+ `assoc_type` longtext NOT NULL
+)
+;
+CREATE TABLE `django_authopenid_userassociation` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `openid_url` varchar(255) NOT NULL,
+ `user_id` integer NOT NULL UNIQUE
+)
+;
+ALTER TABLE `django_authopenid_userassociation` ADD CONSTRAINT user_id_refs_id_f63a9e7163d208d FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `django_authopenid_userpasswordqueue` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL UNIQUE,
+ `new_password` varchar(30) NOT NULL,
+ `confirm_key` varchar(40) NOT NULL
+)
+;
+ALTER TABLE `django_authopenid_userpasswordqueue` ADD CONSTRAINT user_id_refs_id_7f488ca76bcaaa4 FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `django_authopenid_externallogindata` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `external_username` varchar(40) NOT NULL UNIQUE,
+ `external_session_data` longtext NOT NULL,
+ `user_id` integer NULL
+)
+;
+ALTER TABLE `django_authopenid_externallogindata` ADD CONSTRAINT user_id_refs_id_462c0ee2c3e5e139 FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `auth_permission` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `name` varchar(50) NOT NULL,
+ `content_type_id` integer NOT NULL,
+ `codename` varchar(100) NOT NULL,
+ UNIQUE (`content_type_id`, `codename`)
+)
+;
+ALTER TABLE `auth_permission` ADD CONSTRAINT content_type_id_refs_id_6bc81a32728de91f FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`);
+CREATE TABLE `auth_group` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `name` varchar(80) NOT NULL UNIQUE
+)
+;
+CREATE TABLE `auth_user` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `username` varchar(30) NOT NULL UNIQUE,
+ `first_name` varchar(30) NOT NULL,
+ `last_name` varchar(30) NOT NULL,
+ `email` varchar(75) NOT NULL,
+ `password` varchar(128) NOT NULL,
+ `is_staff` bool NOT NULL,
+ `is_active` bool NOT NULL,
+ `is_superuser` bool NOT NULL,
+ `last_login` datetime NOT NULL,
+ `date_joined` datetime NOT NULL,
+ `is_approved` bool NOT NULL,
+ `email_isvalid` bool NOT NULL,
+ `email_key` varchar(32) NULL,
+ `reputation` integer UNSIGNED NOT NULL,
+ `gravatar` varchar(32) NOT NULL,
+ `gold` smallint NOT NULL,
+ `silver` smallint NOT NULL,
+ `bronze` smallint NOT NULL,
+ `questions_per_page` smallint NOT NULL,
+ `last_seen` datetime NOT NULL,
+ `real_name` varchar(100) NOT NULL,
+ `website` varchar(200) NOT NULL,
+ `location` varchar(100) NOT NULL,
+ `date_of_birth` date NULL,
+ `about` longtext NOT NULL
+)
+;
+CREATE TABLE `auth_message` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL,
+ `message` longtext NOT NULL
+)
+;
+ALTER TABLE `auth_message` ADD CONSTRAINT user_id_refs_id_7837edc69af0b65a FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+CREATE TABLE `auth_group_permissions` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `group_id` integer NOT NULL,
+ `permission_id` integer NOT NULL,
+ UNIQUE (`group_id`, `permission_id`)
+)
+;
+ALTER TABLE `auth_group_permissions` ADD CONSTRAINT group_id_refs_id_2ccea4c93cea63fe FOREIGN KEY (`group_id`) REFERENCES `auth_group` (`id`);
+ALTER TABLE `auth_group_permissions` ADD CONSTRAINT permission_id_refs_id_4de83ca7792de1 FOREIGN KEY (`permission_id`) REFERENCES `auth_permission` (`id`);
+CREATE TABLE `auth_user_groups` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL,
+ `group_id` integer NOT NULL,
+ UNIQUE (`user_id`, `group_id`)
+)
+;
+ALTER TABLE `auth_user_groups` ADD CONSTRAINT user_id_refs_id_1993cb70831107f1 FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `auth_user_groups` ADD CONSTRAINT group_id_refs_id_321a8efef0ee9890 FOREIGN KEY (`group_id`) REFERENCES `auth_group` (`id`);
+CREATE TABLE `auth_user_user_permissions` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL,
+ `permission_id` integer NOT NULL,
+ UNIQUE (`user_id`, `permission_id`)
+)
+;
+ALTER TABLE `auth_user_user_permissions` ADD CONSTRAINT user_id_refs_id_166738bf2045483 FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
+ALTER TABLE `auth_user_user_permissions` ADD CONSTRAINT permission_id_refs_id_6d7fb3c2067e79cb FOREIGN KEY (`permission_id`) REFERENCES `auth_permission` (`id`);
+COMMIT;
diff --git a/templates/404.html b/templates/404.html
index 2fa38f99..227de3ae 100644
--- a/templates/404.html
+++ b/templates/404.html
@@ -33,7 +33,7 @@
diff --git a/templates/about.html b/templates/about.html
index eaf0d591..6d5f3060 100644
--- a/templates/about.html
+++ b/templates/about.html
@@ -12,10 +12,35 @@
+
+
{% blocktrans %}CNPROG Q&A is a collaboratively edited question
+ and answer site created for the CNPROG community.
+ {% endblocktrans %}
+
+
{% blocktrans %}Here you can ask and answer questions, comment
+ and vote for the questions of others and their answers. Both questions and answers
+ can be revised and improved. Questions can be tagged with
+ the relevant keywords to simplify future access and organize the accumulated material.{% endblocktrans %}
+
+
+
{% blocktrans %}This Q&A site is moderated by its members, hopefully - including yourself!
+ Moderation rights are gradually assigned to the site users based on the accumulated "reputation"
+ points. These points are added to the users account when others vote for his/her questions or answers.
+ These points (very) roughly reflect the level of trust of the community.{% endblocktrans %}
+
+
{% blocktrans %}No points are necessary to ask or answer the questions - so please -
+ join us!{% endblocktrans %}
+
+
+ {% blocktrans %}
+ If you would like to find out more about this site - please see frequently asked questions.
+ {% endblocktrans %}
+
{% trans "Community gives you awards for your questions, answers and votes." %}
- {% trans "Below is the list of available badges and number of times each type of badge has been awarded." %}
+ {% blocktrans %}Below is the list of available badges and number
+ of times each type of badge has been awarded. Give us feedback at {{feedback_faq_url}}.
+ {% endblocktrans %}
{% for badge in badges %}
@@ -32,7 +34,7 @@
{% endfor %}