summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--README6
-rw-r--r--cnprog.wsgi8
-rw-r--r--forum/views.py3916
-rw-r--r--junk7
-rw-r--r--lanai.psproj557
-rw-r--r--locale/en/LC_MESSAGES/django.mobin367 -> 0 bytes
-rw-r--r--locale/en/LC_MESSAGES/django.po1341
-rw-r--r--locale/es/LC_MESSAGES/django.mobin367 -> 0 bytes
-rw-r--r--locale/es/LC_MESSAGES/django.po1659
-rw-r--r--locale/zh_CN/LC_MESSAGES/django.mobin24652 -> 0 bytes
-rw-r--r--locale/zh_CN/LC_MESSAGES/django.po702
-rw-r--r--middleware/__init__.py0
-rw-r--r--mikes.patch2862
-rw-r--r--settings_local.py21
-rw-r--r--templates/about.html68
-rw-r--r--templates/allfiles30
-rw-r--r--templates/answer_edit_tips.html85
-rw-r--r--templates/authopenid/htmlfiles8
-rw-r--r--templates/badges.html1
-rw-r--r--templates/content/style/default.css12
-rw-r--r--templates/content/style/style.css99
-rw-r--r--templates/faq.html89
-rw-r--r--templates/footer.html21
-rw-r--r--templates/okfiles30
-rw-r--r--templates/pagesize.html2
-rw-r--r--templates/paginator.html14
-rw-r--r--templates/questions.html78
-rw-r--r--templates/tags.html1
-rw-r--r--templates/template.list18
-rw-r--r--templates/tough/faq.html110
-rw-r--r--templates/tough/question_retag.html107
-rw-r--r--templates/tough/unanswered.html115
-rwxr-xr-xtemplates/upfiles/1245715031297631.pngbin0 -> 3863 bytes
-rwxr-xr-xtemplates/upfiles/12457157052552259.pngbin0 -> 3863 bytes
-rw-r--r--templates/users.html1
36 files changed, 8417 insertions, 3552 deletions
diff --git a/.gitignore b/.gitignore
index 18d3733f..4f83efab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
-settings_local.py
*.pyc
*.swp
nbproject
diff --git a/README b/README
new file mode 100644
index 00000000..7f397acf
--- /dev/null
+++ b/README
@@ -0,0 +1,6 @@
+this is based on May23 beta2 version on google code
+
+changes:
+* added internationalization (i18n) messages to templates and .py files
+* added i18n support for javascript + English and Chinese messages
+* site runs as English version
diff --git a/cnprog.wsgi b/cnprog.wsgi
new file mode 100644
index 00000000..a1bd8039
--- /dev/null
+++ b/cnprog.wsgi
@@ -0,0 +1,8 @@
+import os
+import sys
+
+sys.path.append('/var/www/vhosts')
+os.environ['DJANGO_SETTINGS_MODULE'] = 'cnprog.settings'
+
+import django.core.handlers.wsgi
+application = django.core.handlers.wsgi.WSGIHandler()
diff --git a/forum/views.py b/forum/views.py
index 08a0e958..6ac172df 100644
--- a/forum/views.py
+++ b/forum/views.py
@@ -1,1958 +1,1958 @@
-# encoding:utf-8
-import os.path
-import time, datetime, calendar, random
-import logging
-from urllib import quote, unquote
-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.core.paginator import Paginator, EmptyPage, InvalidPage
-from django.template import RequestContext
-from django.utils.html import *
-from django.utils import simplejson
-from django.core import serializers
-from django.db import transaction
-from django.contrib.contenttypes.models import ContentType
-from django.utils.translation import ugettext as _
-
-from utils.html import sanitize_html
-from markdown2 import Markdown
-#from lxml.html.diff import htmldiff
-from forum.diff import textDiff as htmldiff
-from forum.forms import *
-from forum.models import *
-from forum.auth import *
-from forum.const import *
-from forum.user import *
-from forum import auth
-
-# used in index page
-INDEX_PAGE_SIZE = 20
-INDEX_AWARD_SIZE = 15
-INDEX_TAGS_SIZE = 100
-# used in tags list
-DEFAULT_PAGE_SIZE = 60
-# used in questions
-QUESTIONS_PAGE_SIZE = 10
-# used in users
-USERS_PAGE_SIZE = 35
-# used in answers
-ANSWERS_PAGE_SIZE = 10
-markdowner = Markdown(html4tags=True)
-question_type = ContentType.objects.get_for_model(Question)
-answer_type = ContentType.objects.get_for_model(Answer)
-comment_type = ContentType.objects.get_for_model(Comment)
-question_revision_type = ContentType.objects.get_for_model(QuestionRevision)
-answer_revision_type = ContentType.objects.get_for_model(AnswerRevision)
-repute_type =ContentType.objects.get_for_model(Repute)
-question_type_id = question_type.id
-answer_type_id = answer_type.id
-comment_type_id = comment_type.id
-question_revision_type_id = question_revision_type.id
-answer_revision_type_id = answer_revision_type.id
-repute_type_id = repute_type.id
-def _get_tags_cache_json():
- tags = Tag.objects.filter(deleted=False).all()
- tags_list = []
- for tag in tags:
- dic = {'n': tag.name, 'c': tag.used_count }
- tags_list.append(dic)
- tags = simplejson.dumps(tags_list)
- return tags
-
-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)
- # RISK - inner join queries
- questions = questions.select_related()
- tags = Tag.objects.get_valid_tags(INDEX_TAGS_SIZE)
-
- awards = Award.objects.get_recent_awards()
-
- return render_to_response('index.html', {
- "questions" : questions,
- "tab_id" : view_id,
- "tags" : tags,
- "awards" : awards[:INDEX_AWARD_SIZE],
- }, context_instance=RequestContext(request))
-
-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))
-
-def privacy(request):
- return render_to_response('privacy.html', context_instance=RequestContext(request))
-
-def unanswered(request):
- return questions(request, unanswered=True)
-
-def questions(request, tagname=None, unanswered=False):
- """
- List of Questions, Tagged questions, and Unanswered questions.
- """
- # template file
- # "questions.html" or "unanswered.html"
- template_file = "questions.html"
- # Set flag to False by default. If it is equal to True, then need to be saved.
- pagesize_changed = False
- # get pagesize from session, if failed then get default value
- pagesize = request.session.get("pagesize")
- try:
- page = int(request.GET.get('page', '1'))
- 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"
-
- # check if request is from tagged questions
- if tagname is not None:
- objects = Question.objects.get_questions_by_tag(tagname, orderby)
- elif unanswered:
- #check if request is from unanswered questions
- template_file = "unanswered.html"
- objects = Question.objects.get_unanswered_questions(orderby)
- else:
- objects = Question.objects.get_questions(orderby)
-
- # RISK - inner join queries
- objects = objects.select_related(depth=1);
- objects_list = Paginator(objects, pagesize)
- questions = objects_list.page(page)
-
- # Get related tags from this page objects
- if questions.object_list.count() > 0:
- related_tags = Tag.objects.get_tags_by_questions(questions.object_list)
- else:
- related_tags = None
- return render_to_response(template_file, {
- "questions" : questions,
- "tab_id" : view_id,
- "questions_count" : objects_list.count,
- "tags" : related_tags,
- "searchtag" : tagname,
- "is_unanswered" : unanswered,
- "context" : {
- 'is_paginated' : True,
- 'pages': objects_list.num_pages,
- 'page': page,
- 'has_previous': questions.has_previous(),
- 'has_next': questions.has_next(),
- 'previous': questions.previous_page_number(),
- 'next': questions.next_page_number(),
- 'base_url' : request.path + '?sort=%s&' % view_id,
- 'pagesize' : pagesize
- }}, context_instance=RequestContext(request))
-
-#TODO: allow anynomus user to ask question by providing email and username.
-@login_required
-def ask(request):
- if request.method == "POST":
- form = AskForm(request.POST)
- if form.is_valid():
- added_at = datetime.datetime.now()
- html = sanitize_html(markdowner.convert(form.cleaned_data['text']))
- question = Question(
- title = strip_tags(form.cleaned_data['title']),
- author = request.user,
- added_at = added_at,
- last_activity_at = added_at,
- last_activity_by = request.user,
- wiki = form.cleaned_data['wiki'],
- tagnames = form.cleaned_data['tags'].strip(),
- html = html,
- summary = strip_tags(html)[:120]
- )
- if question.wiki:
- question.last_edited_by = question.author
- question.last_edited_at = added_at
- question.wikified_at = added_at
-
- question.save()
-
- # create the first revision
- QuestionRevision.objects.create(
- question = question,
- revision = 1,
- title = question.title,
- author = request.user,
- revised_at = added_at,
- tagnames = question.tagnames,
- summary = CONST['default_version'],
- text = form.cleaned_data['text']
- )
-
- return HttpResponseRedirect(question.get_absolute_url())
-
- else:
- form = AskForm()
-
- tags = _get_tags_cache_json()
- return render_to_response('ask.html', {
- 'form' : form,
- 'tags' : tags,
- }, context_instance=RequestContext(request))
-
-def question(request, id):
- try:
- page = int(request.GET.get('page', '1'))
- except ValueError:
- page = 1
- view_id = request.GET.get('sort', 'votes')
- view_dic = {"latest":"-added_at", "oldest":"added_at", "votes":"-score" }
- try:
- orderby = view_dic[view_id]
- except KeyError:
- view_id = "votes"
- orderby = "-score"
-
- question = get_object_or_404(Question, id=id)
- if question.deleted and not can_view_deleted_post(request.user, question):
- raise Http404
- answer_form = AnswerForm(question)
- answers = Answer.objects.get_answers_from_question(question, request.user)
- answers = answers.select_related(depth=1)
-
- favorited = question.has_favorite_by_user(request.user)
- question_vote = question.votes.select_related().filter(user=request.user)
- if question_vote is not None and question_vote.count() > 0:
- question_vote = question_vote[0]
-
- user_answer_votes = {}
- for answer in answers:
- vote = answer.get_user_vote(request.user)
- if vote is not None and not user_answer_votes.has_key(answer.id):
- vote_value = -1
- if vote.is_upvote():
- vote_value = 1
- user_answer_votes[answer.id] = vote_value
-
-
- if answers is not None:
- answers = answers.order_by("-accepted", orderby)
- objects_list = Paginator(answers, ANSWERS_PAGE_SIZE)
- page_objects = objects_list.page(page)
- # update view count
- Question.objects.update_view_count(question)
- return render_to_response('question.html', {
- "question" : question,
- "question_vote" : question_vote,
- "question_comment_count":question.comments.count(),
- "answer" : answer_form,
- "answers" : page_objects.object_list,
- "user_answer_votes": user_answer_votes,
- "tags" : question.tags.all(),
- "tab_id" : view_id,
- "favorited" : favorited,
- "similar_questions" : Question.objects.get_similar_questions(question),
- "context" : {
- 'is_paginated' : True,
- 'pages': objects_list.num_pages,
- 'page': page,
- 'has_previous': page_objects.has_previous(),
- 'has_next': page_objects.has_next(),
- 'previous': page_objects.previous_page_number(),
- 'next': page_objects.next_page_number(),
- 'base_url' : request.path + '?sort=%s&' % view_id,
- 'extend_url' : "#sort-top"
- }
- }, context_instance=RequestContext(request))
-
-@login_required
-def close(request, id):
- question = get_object_or_404(Question, id=id)
- if not can_close_question(request.user, question):
- return HttpResponse('Permission denied.')
- if request.method == 'POST':
- form = CloseForm(request.POST)
- if form.is_valid():
- reason = form.cleaned_data['reason']
- question.closed = True
- question.closed_by = request.user
- question.closed_at = datetime.datetime.now()
- question.close_reason = reason
- question.save()
- return HttpResponseRedirect(question.get_absolute_url())
- else:
- form = CloseForm()
- return render_to_response('close.html', {
- 'form' : form,
- 'question' : question,
- }, context_instance=RequestContext(request))
-
-@login_required
-def reopen(request, id):
- question = get_object_or_404(Question, id=id)
- # open question
- if not can_reopen_question(request.user, question):
- return HttpResponse('Permission denied.')
- if request.method == 'POST' :
- Question.objects.filter(id=question.id).update(closed=False,
- closed_by=None, closed_at=None, close_reason=None)
- return HttpResponseRedirect(question.get_absolute_url())
- else:
- return render_to_response('reopen.html', {
- 'question' : question,
- }, context_instance=RequestContext(request))
-
-@login_required
-def edit_question(request, id):
- question = get_object_or_404(Question, id=id)
- if question.deleted and not can_view_deleted_post(request.user, question):
- raise Http404
- if can_edit_post(request.user, question):
- return _edit_question(request, question)
- elif can_retag_questions(request.user):
- return _retag_question(request, question)
- else:
- raise Http404
-
-def _retag_question(request, question):
- if request.method == 'POST':
- form = RetagQuestionForm(question, request.POST)
- if form.is_valid():
- if form.has_changed():
- latest_revision = question.get_latest_revision()
- retagged_at = datetime.datetime.now()
- # Update the Question itself
- Question.objects.filter(id=question.id).update(
- tagnames = form.cleaned_data['tags'],
- last_edited_at = retagged_at,
- last_edited_by = request.user,
- last_activity_at = retagged_at,
- last_activity_by = request.user
- )
- # Update the Question's tag associations
- tags_updated = Question.objects.update_tags(question,
- form.cleaned_data['tags'], request.user)
- # Create a new revision
- QuestionRevision.objects.create(
- question = question,
- title = latest_revision.title,
- author = request.user,
- revised_at = retagged_at,
- tagnames = form.cleaned_data['tags'],
- summary = CONST['retagged'],
- text = latest_revision.text
- )
- # send tags updated singal
- tags_updated.send(sender=question.__class__, question=question)
-
- return HttpResponseRedirect(question.get_absolute_url())
- else:
- form = RetagQuestionForm(question)
- return render_to_response('question_retag.html', {
- 'question': question,
- 'form' : form,
- 'tags' : _get_tags_cache_json(),
- }, context_instance=RequestContext(request))
-
-
-def _edit_question(request, question):
- latest_revision = question.get_latest_revision()
- revision_form = None
- if request.method == 'POST':
- if 'select_revision' in request.POST:
- # user has changed revistion number
- revision_form = RevisionForm(question, latest_revision, request.POST)
- if revision_form.is_valid():
- # Replace with those from the selected revision
- form = EditQuestionForm(question,
- QuestionRevision.objects.get(question=question,
- revision=revision_form.cleaned_data['revision']))
- else:
- form = EditQuestionForm(question, latest_revision, request.POST)
- else:
- # Always check modifications against the latest revision
- form = EditQuestionForm(question, latest_revision, request.POST)
- if form.is_valid():
- html = sanitize_html(markdowner.convert(form.cleaned_data['text']))
- if form.has_changed():
- edited_at = datetime.datetime.now()
- tags_changed = (latest_revision.tagnames !=
- form.cleaned_data['tags'])
- tags_updated = False
- # Update the Question itself
- updated_fields = {
- 'title': form.cleaned_data['title'],
- 'last_edited_at': edited_at,
- 'last_edited_by': request.user,
- 'last_activity_at': edited_at,
- 'last_activity_by': request.user,
- 'tagnames': form.cleaned_data['tags'],
- 'summary': strip_tags(html)[:120],
- 'html': html,
- }
-
- # only save when it's checked
- # because wiki doesn't allow to be edited if last version has been enabled already
- # and we make sure this in forms.
- if ('wiki' in form.cleaned_data and
- form.cleaned_data['wiki']):
- updated_fields['wiki'] = True
- updated_fields['wikified_at'] = edited_at
-
- Question.objects.filter(
- id=question.id).update(**updated_fields)
- # Update the Question's tag associations
- if tags_changed:
- tags_updated = Question.objects.update_tags(
- question, form.cleaned_data['tags'], request.user)
- # Create a new revision
- revision = QuestionRevision(
- question = question,
- title = form.cleaned_data['title'],
- author = request.user,
- revised_at = edited_at,
- tagnames = form.cleaned_data['tags'],
- text = form.cleaned_data['text'],
- )
- if form.cleaned_data['summary']:
- revision.summary = form.cleaned_data['summary']
- else:
- revision.summary = 'No.%s Revision' % latest_revision.revision
- revision.save()
-
- return HttpResponseRedirect(question.get_absolute_url())
- else:
-
- revision_form = RevisionForm(question, latest_revision)
- form = EditQuestionForm(question, latest_revision)
- return render_to_response('question_edit.html', {
- 'question': question,
- 'revision_form': revision_form,
- 'form' : form,
- 'tags' : _get_tags_cache_json()
- }, context_instance=RequestContext(request))
-
-
-@login_required
-def edit_answer(request, id):
- answer = get_object_or_404(Answer, id=id)
- if answer.deleted and not can_view_deleted_post(request.user, answer):
- raise Http404
- elif not can_edit_post(request.user, answer):
- raise Http404
- else:
- latest_revision = answer.get_latest_revision()
- if request.method == "POST":
- if 'select_revision' in request.POST:
- # user has changed revistion number
- revision_form = RevisionForm(answer, latest_revision, request.POST)
- if revision_form.is_valid():
- # Replace with those from the selected revision
- form = EditAnswerForm(answer,
- AnswerRevision.objects.get(answer=answer,
- revision=revision_form.cleaned_data['revision']))
- else:
- form = EditAnswerForm(answer, latest_revision, request.POST)
- else:
- form = EditAnswerForm(answer, latest_revision, request.POST)
- if form.is_valid():
- html = sanitize_html(markdowner.convert(form.cleaned_data['text']))
- if form.has_changed():
- edited_at = datetime.datetime.now()
- updated_fields = {
- 'last_edited_at': edited_at,
- 'last_edited_by': request.user,
- 'html': html,
- }
- Answer.objects.filter(id=answer.id).update(**updated_fields)
-
- revision = AnswerRevision(
- answer = answer,
- author = request.user,
- revised_at = edited_at,
- text = form.cleaned_data['text']
- )
-
- if form.cleaned_data['summary']:
- revision.summary = form.cleaned_data['summary']
- else:
- revision.summary = 'No.%s Revision' % latest_revision.revision
- revision.save()
-
- answer.question.last_activity_at = edited_at
- answer.question.last_activity_by = request.user
- answer.question.save()
-
- return HttpResponseRedirect(answer.get_absolute_url())
- else:
- revision_form = RevisionForm(answer, latest_revision)
- form = EditAnswerForm(answer, latest_revision)
- return render_to_response('answer_edit.html', {
- 'answer': answer,
- 'revision_form': revision_form,
- 'form' : form,
- }, context_instance=RequestContext(request))
-
-QUESTION_REVISION_TEMPLATE = ('<h1>%(title)s</h1>\n'
- '<div class="text">%(html)s</div>\n'
- '<div class="tags">%(tags)s</div>')
-def question_revisions(request, id):
- post = get_object_or_404(Question, id=id)
- revisions = list(post.revisions.all())
- for i, revision in enumerate(revisions):
- revision.html = QUESTION_REVISION_TEMPLATE % {
- 'title': revision.title,
- 'html': sanitize_html(markdowner.convert(revision.text)),
- 'tags': ' '.join(['<a class="post-tag">%s</a>' % tag
- for tag in revision.tagnames.split(' ')]),
- }
- if i > 0:
- revisions[i - 1].diff = htmldiff(revision.html,
- revisions[i - 1].html)
- else:
- revisions[i - 1].diff = QUESTION_REVISION_TEMPLATE % {
- 'title': revisions[0].title,
- 'html': sanitize_html(markdowner.convert(revisions[0].text)),
- 'tags': ' '.join(['<a class="post-tag">%s</a>' % tag
- for tag in revisions[0].tagnames.split(' ')]),
- }
- revisions[i - 1].summary = None
- return render_to_response('revisions_question.html', {
- 'post': post,
- 'revisions': revisions,
- }, context_instance=RequestContext(request))
-
-ANSWER_REVISION_TEMPLATE = ('<div class="text">%(html)s</div>')
-def answer_revisions(request, id):
- post = get_object_or_404(Answer, id=id)
- revisions = list(post.revisions.all())
- 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)
- else:
- revisions[i - 1].diff = revisions[i-1].text
- revisions[i - 1].summary = None
- return render_to_response('revisions_answer.html', {
- 'post': post,
- 'revisions': revisions,
- }, context_instance=RequestContext(request))
-
-#TODO: allow anynomus
-@login_required
-def answer(request, id):
- question = get_object_or_404(Question, id=id)
- if request.method == "POST":
- form = AnswerForm(question, request.POST)
- if form.is_valid():
- update_time = datetime.datetime.now()
- answer = Answer(
- question = question,
- author = request.user,
- added_at = update_time,
- wiki = form.cleaned_data['wiki'],
- html = sanitize_html(markdowner.convert(form.cleaned_data['text'])),
- )
- if answer.wiki:
- answer.last_edited_by = answer.author
- answer.last_edited_at = update_time
- answer.wikified_at = update_time
-
- answer.save()
- Question.objects.update_answer_count(question)
-
- question = get_object_or_404(Question, id=id)
- question.last_activity_at = update_time
- question.last_activity_by = request.user
- question.save()
-
- AnswerRevision.objects.create(
- answer = answer,
- revision = 1,
- author = request.user,
- revised_at = update_time,
- summary = CONST['default_version'],
- text = form.cleaned_data['text']
- )
-
- return HttpResponseRedirect(question.get_absolute_url())
-
-def tags(request):
- stag = ""
- is_paginated = True
- sortby = request.GET.get('sort', 'used')
- try:
- page = int(request.GET.get('page', '1'))
- except ValueError:
- page = 1
-
- if request.method == "GET":
- stag = request.GET.get("q", "").strip()
- if stag is not None:
- 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":
- objects_list = Paginator(Tag.objects.all().filter(deleted=False).exclude(used_count=0).order_by("name"), DEFAULT_PAGE_SIZE)
- else:
- objects_list = Paginator(Tag.objects.all().filter(deleted=False).exclude(used_count=0).order_by("-used_count"), DEFAULT_PAGE_SIZE)
-
- try:
- tags = objects_list.page(page)
- except (EmptyPage, InvalidPage):
- tags = objects_list.page(objects_list.num_pages)
-
- return render_to_response('tags.html', {
- "tags" : tags,
- "stag" : stag,
- "tab_id" : sortby,
- "keywords" : stag,
- "context" : {
- 'is_paginated' : is_paginated,
- 'pages': objects_list.num_pages,
- 'page': page,
- 'has_previous': tags.has_previous(),
- 'has_next': tags.has_next(),
- 'previous': tags.previous_page_number(),
- 'next': tags.next_page_number(),
- 'base_url' : '/tags/?sort=%s&' % sortby
- }
-
- }, context_instance=RequestContext(request))
-
-def tag(request, tag):
- return questions(request, tagname=tag)
-
-def vote(request, id):
- """
- vote_type:
- acceptAnswer : 0,
- questionUpVote : 1,
- questionDownVote : 2,
- favorite : 4,
- answerUpVote: 5,
- answerDownVote:6,
- offensiveQuestion : 7,
- offensiveAnswer:8,
- removeQuestion: 9,
- removeAnswer:10
-
- accept answer code:
- response_data['allowed'] = -1, Accept his own answer 0, no allowed - Anonymous 1, Allowed - by default
- response_data['success'] = 0, failed 1, Success - by default
- response_data['status'] = 0, By default 1, Answer has been accepted already(Cancel)
-
- vote code:
- allowed = -3, Don't have enough votes left
- -2, Don't have enough reputation score
- -1, Vote his own post
- 0, no allowed - Anonymous
- 1, Allowed - by default
- status = 0, By default
- 1, Cancel
- 2, Vote is too old to be canceled
-
- offensive code:
- allowed = -3, Don't have enough flags left
- -2, Don't have enough reputation score to do this
- 0, not allowed
- 1, allowed
- status = 0, by default
- 1, can't do it again
- """
- response_data = {
- "allowed": 1,
- "success": 1,
- "status" : 0,
- "count" : 0,
- "message" : ''
- }
-
- def can_vote(vote_score, user):
- if vote_score == 1:
- return can_vote_up(request.user)
- else:
- return can_vote_down(request.user)
-
- try:
- if not request.user.is_authenticated():
- response_data['allowed'] = 0
- response_data['success'] = 0
-
- elif request.is_ajax():
- question = get_object_or_404(Question, id=id)
- vote_type = request.POST.get('type')
-
- #accept answer
- if vote_type == '0':
- answer_id = request.POST.get('postId')
- answer = get_object_or_404(Answer, id=answer_id)
- # make sure question author is current user
- if question.author == request.user:
- # answer user who is also question author is not allow to accept answer
- if answer.author == question.author:
- response_data['success'] = 0
- response_data['allowed'] = -1
- # check if answer has been accepted already
- elif answer.accepted:
- onAnswerAcceptCanceled(answer, request.user)
- response_data['status'] = 1
- else:
- # set other answers in this question not accepted first
- for answer_of_question in Answer.objects.get_answers_from_question(question, request.user):
- if answer_of_question != answer and answer_of_question.accepted:
- onAnswerAcceptCanceled(answer_of_question, request.user)
-
- #make sure retrieve data again after above author changes, they may have related data
- answer = get_object_or_404(Answer, id=answer_id)
- onAnswerAccept(answer, request.user)
- else:
- response_data['allowed'] = 0
- response_data['success'] = 0
- # favorite
- elif vote_type == '4':
- has_favorited = False
- fav_questions = FavoriteQuestion.objects.filter(question=question)
- # if the same question has been favorited before, then delete it
- if fav_questions is not None:
- for item in fav_questions:
- if item.user == request.user:
- item.delete()
- response_data['status'] = 1
- response_data['count'] = len(fav_questions) - 1
- if response_data['count'] < 0:
- response_data['count'] = 0
- has_favorited = True
- # if above deletion has not been executed, just insert a new favorite question
- if not has_favorited:
- new_item = FavoriteQuestion(question=question, user=request.user)
- new_item.save()
- response_data['count'] = FavoriteQuestion.objects.filter(question=question).count()
- Question.objects.update_favorite_count(question)
-
- elif vote_type in ['1', '2', '5', '6']:
- post_id = id
- post = question
- vote_score = 1
- if vote_type in ['5', '6']:
- answer_id = request.POST.get('postId')
- answer = get_object_or_404(Answer, id=answer_id)
- post_id = answer_id
- post = answer
- if vote_type in ['2', '6']:
- vote_score = -1
-
- if post.author == request.user:
- response_data['allowed'] = -1
- elif not can_vote(vote_score, request.user):
- response_data['allowed'] = -2
- elif post.votes.filter(user=request.user).count() > 0:
- vote = post.votes.filter(user=request.user)[0]
- # unvote should be less than certain time
- if (datetime.datetime.now().day - vote.voted_at.day) >= VOTE_RULES['scope_deny_unvote_days']:
- response_data['status'] = 2
- else:
- voted = vote.vote
- if voted > 0:
- # cancel upvote
- onUpVotedCanceled(vote, post, request.user)
-
- else:
- # cancel downvote
- onDownVotedCanceled(vote, post, request.user)
-
- response_data['status'] = 1
- response_data['count'] = post.score
- elif Vote.objects.get_votes_count_today_from_user(request.user) >= VOTE_RULES['scope_votes_per_user_per_day']:
- response_data['allowed'] = -3
- else:
- vote = Vote(user=request.user, content_object=post, vote=vote_score, voted_at=datetime.datetime.now())
- if vote_score > 0:
- # upvote
- onUpVoted(vote, post, request.user)
- else:
- # downvote
- onDownVoted(vote, post, request.user)
-
- votes_left = VOTE_RULES['scope_votes_per_user_per_day'] - Vote.objects.get_votes_count_today_from_user(request.user)
- if votes_left <= VOTE_RULES['scope_warn_votes_left']:
- response_data['message'] = u'%s votes left' % votes_left
- response_data['count'] = post.score
- elif vote_type in ['7', '8']:
- post = question
- post_id = id
- if vote_type == '8':
- post_id = request.POST.get('postId')
- post = get_object_or_404(Answer, id=post_id)
-
- if FlaggedItem.objects.get_flagged_items_count_today(request.user) >= VOTE_RULES['scope_flags_per_user_per_day']:
- response_data['allowed'] = -3
- elif not can_flag_offensive(request.user):
- response_data['allowed'] = -2
- elif post.flagged_items.filter(user=request.user).count() > 0:
- response_data['status'] = 1
- else:
- item = FlaggedItem(user=request.user, content_object=post, flagged_at=datetime.datetime.now())
- onFlaggedItem(item, post, request.user)
- response_data['count'] = post.offensive_flag_count
- # send signal when question or answer be marked offensive
- mark_offensive.send(sender=post.__class__, instance=post, mark_by=request.user)
- elif vote_type in ['9', '10']:
- post = question
- post_id = id
- if vote_type == '10':
- post_id = request.POST.get('postId')
- post = get_object_or_404(Answer, id=post_id)
-
- if not can_delete_post(request.user, post):
- response_data['allowed'] = -2
- elif post.deleted:
- onDeleteCanceled(post, request.user)
- response_data['status'] = 1
- else:
- onDeleted(post, request.user)
- delete_post_or_answer.send(sender=post.__class__, instance=post, delete_by=request.user)
- else:
- response_data['success'] = 0
- response_data['message'] = u'Request mode is not supported. Please try again.'
-
- data = simplejson.dumps(response_data)
-
- except Exception, e:
- response_data['message'] = str(e)
- data = simplejson.dumps(response_data)
- return HttpResponse(data, mimetype="application/json")
-
-def users(request):
- is_paginated = True
- sortby = request.GET.get('sort', 'reputation')
- suser = request.REQUEST.get('q', "")
- try:
- page = int(request.GET.get('page', '1'))
- except ValueError:
- page = 1
-
- if suser == "":
- if sortby == "newest":
- objects_list = Paginator(User.objects.all().order_by('-date_joined'), USERS_PAGE_SIZE)
- elif sortby == "last":
- objects_list = Paginator(User.objects.all().order_by('date_joined'), USERS_PAGE_SIZE)
- elif sortby == "user":
- objects_list = Paginator(User.objects.all().order_by('username'), USERS_PAGE_SIZE)
- # default
- else:
- objects_list = Paginator(User.objects.all().order_by('-reputation'), USERS_PAGE_SIZE)
- base_url = '/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 = '/users/?name=%s&sort=%s&' % (suser, sortby)
-
- try:
- users = objects_list.page(page)
- except (EmptyPage, InvalidPage):
- users = objects_list.page(objects_list.num_pages)
-
- return render_to_response('users.html', {
- "users" : users,
- "suser" : suser,
- "keywords" : suser,
- "tab_id" : sortby,
- "context" : {
- 'is_paginated' : is_paginated,
- 'pages': objects_list.num_pages,
- 'page': page,
- 'has_previous': users.has_previous(),
- 'has_next': users.has_next(),
- 'previous': users.previous_page_number(),
- 'next': users.next_page_number(),
- 'base_url' : base_url
- }
-
- }, context_instance=RequestContext(request))
-
-def user(request, id):
- sort = request.GET.get('sort', 'stats')
- user_view = dict((v.id, v) for v in USER_TEMPLATE_VIEWS).get(sort, USER_TEMPLATE_VIEWS[0])
- from forum import views
- func = getattr(views, user_view.view_name)
- return func(request, id, user_view)
-
-@login_required
-def edit_user(request, id):
- user = get_object_or_404(User, id=id)
- if request.user != user:
- raise Http404
- if request.method == "POST":
- form = EditUserForm(user, request.POST)
- if form.is_valid():
- user.email = sanitize_html(form.cleaned_data['email'])
- user.real_name = sanitize_html(form.cleaned_data['realname'])
- user.website = sanitize_html(form.cleaned_data['website'])
- user.location = sanitize_html(form.cleaned_data['city'])
- user.date_of_birth = sanitize_html(form.cleaned_data['birthday'])
- if len(user.date_of_birth) == 0:
- user.date_of_birth = '1900-01-01'
- user.about = sanitize_html(form.cleaned_data['about'])
-
- user.save()
- # send user updated singal if full fields have been updated
- if user.email and user.real_name and user.website and user.location and \
- user.date_of_birth and user.about:
- user_updated.send(sender=user.__class__, instance=user, updated_by=user)
- return HttpResponseRedirect(user.get_profile_url())
- else:
- form = EditUserForm(user)
- return render_to_response('user_edit.html', {
- 'form' : form,
- }, context_instance=RequestContext(request))
-
-def user_stats(request, user_id, user_view):
- user = get_object_or_404(User, id=user_id)
- questions = Question.objects.extra(
- select={
- 'vote_count' : 'question.score',
- 'favorited_myself' : 'SELECT count(*) FROM favorite_question f WHERE f.user_id = %s AND f.question_id = question.id',
- 'la_user_id' : 'auth_user.id',
- 'la_username' : 'auth_user.username',
- 'la_user_gold' : 'auth_user.gold',
- 'la_user_silver' : 'auth_user.silver',
- 'la_user_bronze' : 'auth_user.bronze',
- 'la_user_reputation' : 'auth_user.reputation'
- },
- select_params=[user_id],
- tables=['question', 'auth_user'],
- where=['question.deleted = 0 AND question.author_id=%s AND question.last_activity_by_id = auth_user.id'],
- params=[user_id],
- order_by=['-vote_count', '-last_activity_at']
- ).values('vote_count',
- 'favorited_myself',
- 'id',
- 'title',
- 'author_id',
- 'added_at',
- 'answer_accepted',
- 'answer_count',
- 'comment_count',
- 'view_count',
- 'favourite_count',
- 'summary',
- 'tagnames',
- 'vote_up_count',
- 'vote_down_count',
- 'last_activity_at',
- 'la_user_id',
- 'la_username',
- 'la_user_gold',
- 'la_user_silver',
- 'la_user_bronze',
- 'la_user_reputation')[:100]
-
- answered_questions = Question.objects.extra(
- select={
- 'vote_up_count' : 'answer.vote_up_count',
- 'vote_down_count' : 'answer.vote_down_count',
- 'answer_id' : 'answer.id',
- 'accepted' : 'answer.accepted',
- 'vote_count' : 'answer.score',
- 'comment_count' : 'answer.comment_count'
- },
- tables=['question', 'answer'],
- where=['answer.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]
- ).distinct().values('comment_count',
- 'id',
- 'answer_id',
- 'title',
- 'author_id',
- 'accepted',
- 'vote_count',
- 'answer_count',
- 'vote_up_count',
- 'vote_down_count')[:100]
- up_votes = Vote.objects.get_up_vote_count_from_user(user)
- down_votes = Vote.objects.get_down_vote_count_from_user(user)
- votes_today = Vote.objects.get_votes_count_today_from_user(user)
- votes_total = VOTE_RULES['scope_votes_per_user_per_day']
- tags = user.created_tags.all().order_by('-used_count')[:50]
- awards = Award.objects.extra(
- select={'id': 'badge.id', 'count': 'count(badge_id)', 'name':'badge.name', 'description': 'badge.description', 'type': 'badge.type'},
- tables=['award', 'badge'],
- order_by=['-awarded_at'],
- where=['user_id=%s AND badge_id=badge.id'],
- params=[user.id]
- ).values('id', 'count', 'name', 'description', 'type')
- total_awards = awards.count()
- awards.query.group_by = ['badge_id']
-
- 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,
- "questions" : questions,
- "answered_questions" : answered_questions,
- "up_votes" : up_votes,
- "down_votes" : down_votes,
- "total_votes": up_votes + down_votes,
- "votes_today_left": votes_total-votes_today,
- "votes_total_per_day": votes_total,
- "tags" : tags,
- "awards": awards,
- "total_awards" : total_awards,
- }, context_instance=RequestContext(request))
-
-def user_recent(request, user_id, user_view):
- user = get_object_or_404(User, id=user_id)
- def get_type_name(type_id):
- for item in TYPE_ACTIVITY:
- if type_id in item:
- return item[1]
-
- class Event:
- def __init__(self, time, type, title, summary, answer_id, question_id):
- self.time = time
- self.type = get_type_name(type)
- self.type_id = type
- self.title = title
- self.summary = summary
- self.title_link = u'/questions/%s/%s#%s' %(question_id, title, answer_id)\
- if int(answer_id) > 0 else u'/questions/%s/%s' %(question_id, title)
- class AwardEvent:
- def __init__(self, time, type, id):
- self.time = time
- self.type = get_type_name(type)
- self.type_id = type
- self.badge = get_object_or_404(Badge, id=id)
-
- activities = []
- # ask questions
- questions = Activity.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'active_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type'
- },
- 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'],
- params=[question_type_id, user_id, TYPE_ACTIVITY_ASK_QUESTION],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'active_at',
- 'activity_type'
- )
- if len(questions) > 0:
- questions = [(Event(q['active_at'], q['activity_type'], q['title'], '', '0', \
- q['question_id'])) for q in questions]
- activities.extend(questions)
-
- # answers
- answers = Activity.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'active_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type'
- },
- 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'],
- params=[answer_type_id, user_id, TYPE_ACTIVITY_ANSWER],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'active_at',
- 'activity_type'
- )
- if len(answers) > 0:
- answers = [(Event(q['active_at'], q['activity_type'], q['title'], '', q['answer_id'], \
- q['question_id'])) for q in answers]
- activities.extend(answers)
-
- # question comments
- comments = Activity.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'comment.object_id',
- 'added_at' : 'comment.added_at',
- 'activity_type' : 'activity.activity_type'
- },
- tables=['activity', 'question', 'comment'],
-
- 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'],
- params=[comment_type_id, question_type_id, user_id, TYPE_ACTIVITY_COMMENT_QUESTION],
- order_by=['-comment.added_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'activity_type'
- )
-
- if len(comments) > 0:
- comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \
- q['question_id'])) for q in comments]
- activities.extend(comments)
-
- # answer comments
- comments = Activity.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'added_at' : 'comment.added_at',
- 'activity_type' : 'activity.activity_type'
- },
- tables=['activity', 'question', 'answer', 'comment'],
-
- 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'],
- params=[comment_type_id, answer_type_id, user_id, TYPE_ACTIVITY_COMMENT_ANSWER],
- order_by=['-comment.added_at']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'added_at',
- 'activity_type'
- )
-
- if len(comments) > 0:
- comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', q['answer_id'], \
- q['question_id'])) for q in comments]
- activities.extend(comments)
-
- # question revisions
- revisions = Activity.objects.extra(
- select={
- 'title' : 'question_revision.title',
- 'question_id' : 'question_revision.question_id',
- 'added_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type',
- 'summary' : 'question_revision.summary'
- },
- tables=['activity', 'question_revision'],
- where=['activity.content_type_id = %s AND activity.object_id = question_revision.id 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],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'activity_type',
- 'summary'
- )
-
- if len(revisions) > 0:
- revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], '0', \
- q['question_id'])) for q in revisions]
- activities.extend(revisions)
-
- # answer revisions
- revisions = Activity.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'added_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type',
- 'summary' : 'answer_revision.summary'
- },
- tables=['activity', 'answer_revision', 'question', 'answer'],
-
- 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 '+
- 'activity.activity_type=%s'],
- params=[answer_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_ANSWER],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'answer_id',
- 'activity_type',
- 'summary'
- )
-
- if len(revisions) > 0:
- revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], \
- q['answer_id'], q['question_id'])) for q in revisions]
- activities.extend(revisions)
-
- # accepted answers
- accept_answers = Activity.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'added_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type',
- },
- 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.question_id=question.id AND activity.activity_type=%s'],
- params=[answer_type_id, user_id, TYPE_ACTIVITY_MARK_ANSWER],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'activity_type',
- )
- if len(accept_answers) > 0:
- accept_answers = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \
- q['question_id'])) for q in accept_answers]
- activities.extend(accept_answers)
- #award history
- awards = Activity.objects.extra(
- select={
- 'badge_id' : 'badge.id',
- 'awarded_at': 'award.awarded_at',
- 'activity_type' : 'activity.activity_type'
- },
- tables=['activity', 'award', 'badge'],
- where=['activity.user_id = award.user_id AND activity.user_id = %s AND '+
- 'award.badge_id=badge.id AND activity.object_id=award.id AND activity.activity_type=%s'],
- params=[user_id, TYPE_ACTIVITY_PRIZE],
- order_by=['-activity.active_at']
- ).values(
- 'badge_id',
- 'awarded_at',
- 'activity_type'
- )
- if len(awards) > 0:
- awards = [(AwardEvent(q['awarded_at'], q['activity_type'], q['badge_id'])) for q in awards]
- activities.extend(awards)
-
- activities.sort(lambda x,y: cmp(y.time, x.time))
-
- 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,
- "activities" : activities[:user_view.data_size]
- }, context_instance=RequestContext(request))
-
-def user_responses(request, user_id, user_view):
- """
- We list answers for question, comments, and answer accepted by others for this user.
- """
- class Response:
- def __init__(self, type, title, question_id, answer_id, time, username, user_id, content):
- self.type = type
- self.title = title
- self.titlelink = u'/questions/%s/%s#%s' % (question_id, title, answer_id)
- self.time = time
- self.userlink = u'/users/%s/%s/' % (user_id, username)
- self.username = username
- self.content = u'%s ...' % strip_tags(content)[:300]
-
- def __unicode__(self):
- return u'%s %s' % (self.type, self.titlelink)
-
- user = get_object_or_404(User, id=user_id)
- responses = []
- answers = Answer.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'added_at' : 'answer.added_at',
- 'html' : 'answer.html',
- 'username' : 'auth_user.username',
- 'user_id' : 'auth_user.id'
- },
- select_params=[user_id],
- tables=['answer', 'question', 'auth_user'],
- where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND '+
- 'question.author_id = %s AND answer.author_id <> %s AND answer.author_id=auth_user.id'],
- params=[user_id, user_id],
- order_by=['-answer.id']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'added_at',
- 'html',
- 'username',
- 'user_id'
- )
- if len(answers) > 0:
- answers = [(Response(TYPE_RESPONSE['QUESTION_ANSWERED'], a['title'], a['question_id'],
- a['answer_id'], a['added_at'], a['username'], a['user_id'], a['html'])) for a in answers]
- responses.extend(answers)
-
-
- # question comments
- comments = Comment.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'comment.object_id',
- 'added_at' : 'comment.added_at',
- 'comment' : 'comment.comment',
- 'username' : 'auth_user.username',
- 'user_id' : 'auth_user.id'
- },
- tables=['question', 'auth_user', 'comment'],
- where=['question.deleted = 0 AND question.author_id = %s AND comment.object_id=question.id AND '+
- 'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id'],
- params=[user_id, question_type_id, user_id],
- order_by=['-comment.added_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'comment',
- 'username',
- 'user_id'
- )
-
- if len(comments) > 0:
- comments = [(Response(TYPE_RESPONSE['QUESTION_COMMENTED'], c['title'], c['question_id'],
- '', c['added_at'], c['username'], c['user_id'], c['comment'])) for c in comments]
- responses.extend(comments)
-
- # answer comments
- comments = Comment.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'added_at' : 'comment.added_at',
- 'comment' : 'comment.comment',
- 'username' : 'auth_user.username',
- 'user_id' : 'auth_user.id'
- },
- tables=['answer', 'auth_user', 'comment', 'question'],
- where=['answer.deleted = 0 AND answer.author_id = %s AND comment.object_id=answer.id AND '+
- 'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id '+
- 'AND question.id = answer.question_id'],
- params=[user_id, answer_type_id, user_id],
- order_by=['-comment.added_at']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'added_at',
- 'comment',
- 'username',
- 'user_id'
- )
-
- if len(comments) > 0:
- comments = [(Response(TYPE_RESPONSE['ANSWER_COMMENTED'], c['title'], c['question_id'],
- c['answer_id'], c['added_at'], c['username'], c['user_id'], c['comment'])) for c in comments]
- responses.extend(comments)
-
- # answer has been accepted
- answers = Answer.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'added_at' : 'answer.accepted_at',
- 'html' : 'answer.html',
- 'username' : 'auth_user.username',
- 'user_id' : 'auth_user.id'
- },
- select_params=[user_id],
- tables=['answer', 'question', 'auth_user'],
- where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND '+
- 'answer.author_id = %s AND answer.accepted=1 AND question.author_id=auth_user.id'],
- params=[user_id],
- order_by=['-answer.id']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'added_at',
- 'html',
- 'username',
- 'user_id'
- )
- if len(answers) > 0:
- answers = [(Response(TYPE_RESPONSE['ANSWER_ACCEPTED'], a['title'], a['question_id'],
- a['answer_id'], a['added_at'], a['username'], a['user_id'], a['html'])) for a in answers]
- responses.extend(answers)
-
- # sort posts by time
- responses.sort(lambda x,y: cmp(y.time, x.time))
-
- 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,
- "responses" : responses[:user_view.data_size],
-
- }, context_instance=RequestContext(request))
-
-def user_votes(request, user_id, user_view):
- user = get_object_or_404(User, id=user_id)
- if not can_view_user_votes(request.user, user):
- raise Http404
- votes = []
- question_votes = Vote.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'answer_id' : 0,
- 'voted_at' : 'vote.voted_at',
- 'vote' : 'vote',
- },
- select_params=[user_id],
- tables=['vote', 'question', 'auth_user'],
- where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = question.id '+
- 'AND vote.user_id=auth_user.id'],
- params=[question_type_id, user_id],
- order_by=['-vote.id']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'voted_at',
- 'vote',
- )
- if(len(question_votes) > 0):
- votes.extend(question_votes)
-
- answer_votes = Vote.objects.extra(
- select={
- 'title' : 'question.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'voted_at' : 'vote.voted_at',
- 'vote' : 'vote',
- },
- select_params=[user_id],
- tables=['vote', 'answer', 'question', 'auth_user'],
- where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = answer.id '+
- 'AND answer.question_id = question.id AND vote.user_id=auth_user.id'],
- params=[answer_type_id, user_id],
- order_by=['-vote.id']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'voted_at',
- 'vote',
- )
- if(len(answer_votes) > 0):
- votes.extend(answer_votes)
- votes.sort(lambda x,y: cmp(y['voted_at'], x['voted_at']))
- 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,
- "votes" : votes[:user_view.data_size]
-
- }, context_instance=RequestContext(request))
-
-def user_reputation(request, user_id, user_view):
- user = get_object_or_404(User, id=user_id)
- reputation = Repute.objects.extra(
- select={'positive': 'sum(positive)', 'negative': 'sum(negative)', 'question_id':'question_id',
- 'title': 'question.title'},
- tables=['repute', 'question'],
- order_by=['-reputed_at'],
- where=['user_id=%s AND question_id=question.id'],
- params=[user.id]
- ).values('positive', 'negative', 'question_id', 'title', 'reputed_at', 'reputation')
-
- reputation.query.group_by = ['question_id']
-
-
- rep_list = []
- for rep in Repute.objects.filter(user=user).order_by('reputed_at'):
- dic = '[%s,%s]' % (calendar.timegm(rep.reputed_at.timetuple()) * 1000, rep.reputation)
- rep_list.append(dic)
- reps = ','.join(rep_list)
- reps = '[%s]' % reps
-
- 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,
- "reputation" : reputation,
- "reps" : reps
- }, context_instance=RequestContext(request))
-
-def user_favorites(request, user_id, user_view):
- user = get_object_or_404(User, id=user_id)
- questions = Question.objects.extra(
- select={
- 'vote_count' : 'question.vote_up_count + question.vote_down_count',
- 'favorited_myself' : 'SELECT count(*) FROM favorite_question f WHERE f.user_id = %s '+
- 'AND f.question_id = question.id',
- 'la_user_id' : 'auth_user.id',
- 'la_username' : 'auth_user.username',
- 'la_user_gold' : 'auth_user.gold',
- 'la_user_silver' : 'auth_user.silver',
- 'la_user_bronze' : 'auth_user.bronze',
- 'la_user_reputation' : 'auth_user.reputation'
- },
- select_params=[user_id],
- tables=['question', 'auth_user', 'favorite_question'],
- where=['question.deleted = 0 AND question.last_activity_by_id = auth_user.id '+
- 'AND favorite_question.question_id = question.id AND favorite_question.user_id = %s'],
- params=[user_id],
- order_by=['-vote_count', '-question.id']
- ).values('vote_count',
- 'favorited_myself',
- 'id',
- 'title',
- 'author_id',
- 'added_at',
- 'answer_accepted',
- 'answer_count',
- 'comment_count',
- 'view_count',
- 'favourite_count',
- 'summary',
- 'tagnames',
- 'vote_up_count',
- 'vote_down_count',
- 'last_activity_at',
- 'la_user_id',
- 'la_username',
- 'la_user_gold',
- 'la_user_silver',
- 'la_user_bronze',
- 'la_user_reputation')
- 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,
- "questions" : questions[:user_view.data_size],
- "view_user" : user
- }, context_instance=RequestContext(request))
-
-
-def user_preferences(request, user_id, user_view):
- user = get_object_or_404(User, id=user_id)
- 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,
- }, 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)
-
-def answer_comments(request, id):
- answer = get_object_or_404(Answer, id=id)
- user = request.user
- return __comments(request, answer, 'answer', user)
-
-def __comments(request, obj, type, user):
- # only support get comments by ajax now
- if request.is_ajax():
- if request.method == "GET":
- return __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)
-
-def __generate_comments_json(obj, type, user):
- 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 = []
- 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)
- json_comments.append({"id" : comment.id,
- "object_id" : obj.id,
- "add_date" : comment.added_at.strftime('%Y-%m-%d'),
- "text" : comment.comment,
- "user_display_name" : comment_user.username,
- "user_url" : "/users/%s/%s" % (comment_user.id, comment_user.username),
- "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_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)
-
-def logout(request):
- url = request.GET.get('next')
- return render_to_response('logout.html', {
- 'next' : url,
- }, context_instance=RequestContext(request))
-
-def badges(request):
- badges = Badge.objects.all().order_by('type')
- my_badges = []
- if request.user.is_authenticated():
- my_badges = Award.objects.filter(user=request.user)
- my_badges.query.group_by = ['badge_id']
-
- return render_to_response('badges.html', {
- 'badges' : badges,
- 'mybadges' : my_badges,
- }, context_instance=RequestContext(request))
-
-def badge(request, id):
- badge = get_object_or_404(Badge, id=id)
- awards = Award.objects.extra(
- select={'id': 'auth_user.id',
- 'name': 'auth_user.username',
- 'rep':'auth_user.reputation',
- 'gold': 'auth_user.gold',
- 'silver': 'auth_user.silver',
- 'bronze': 'auth_user.bronze'},
- tables=['award', 'auth_user'],
- where=['badge_id=%s AND user_id=auth_user.id'],
- params=[id]
- ).values('id').distinct()
-
- return render_to_response('badge.html', {
- 'awards' : awards,
- 'badge' : badge,
- }, context_instance=RequestContext(request))
-
-def read_message(request):
- if request.method == "POST":
- if request.POST['formdata'] == 'required':
- request.session['message_silent'] = 1
-
- if request.user.is_authenticated():
- request.user.delete_messages()
- return HttpResponse('')
-
-def upload(request):
- class FileTypeNotAllow(Exception):
- pass
- class FileSizeNotAllow(Exception):
- pass
- class UploadPermissionNotAuthorized(Exception):
- pass
-
- #<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>
- xml_template = "<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>"
-
- try:
- f = request.FILES['file-upload']
- # check upload permission
- if not can_upload_files(request.user):
- raise UploadPermissionNotAuthorized
-
- # check file type
- file_name_suffix = os.path.splitext(f.name)[1].lower()
- if not file_name_suffix in settings.ALLOW_FILE_TYPES:
- raise FileTypeNotAllow
-
- # genetate new file name
- new_file_name = str(time.time()).replace('.', str(random.randint(0,100000))) + file_name_suffix
- # use default storage to store file
- default_storage.save(new_file_name, f)
- # check file size
- # byte
- size = default_storage.size(new_file_name)
- if size > settings.ALLOW_MAX_FILE_SIZE:
- default_storage.delete(new_file_name)
- raise FileSizeNotAllow
-
- result = xml_template % ('Good', '', default_storage.url(new_file_name))
- except UploadPermissionNotAuthorized:
- result = xml_template % ('', _('uploading images is limited to users with >60 reputation points'), '')
- except FileTypeNotAllow:
- result = xml_template % ('', _("allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"), '')
- except FileSizeNotAllow:
- result = xml_template % ('', _("maximum upload file size is %sK") % settings.ALLOW_MAX_FILE_SIZE / 1024, '')
- except Exception as e:
- result = xml_template % ('', _('Error uploading file. Please contact the site administrator. Thank you. %s' % e), '')
-
- return HttpResponse(result, mimetype="application/xml")
-
-def books(request):
- return HttpResponseRedirect("/books/mysql-zhaoyang")
-
-def book(request, short_name, unanswered=False):
- """
- 1. questions list
- 2. book info
- 3. author info and blog rss items
- """
- """
- List of Questions, Tagged questions, and Unanswered questions.
- """
- books = Book.objects.extra(where=['short_name = %s'], params=[short_name])
- match_count = len(books)
- if match_count == 0 :
- raise Http404
- else:
- # the book info
- book = books[0]
- # get author info
- author_info = BookAuthorInfo.objects.get(book=book)
- # get author rss info
- author_rss = BookAuthorRss.objects.filter(book=book)
-
- # get pagesize from session, if failed then get default value
- user_page_size = request.session.get("pagesize", QUESTIONS_PAGE_SIZE)
- # set pagesize equal to logon user specified value in database
- if request.user.is_authenticated() and request.user.questions_per_page > 0:
- user_page_size = request.user.questions_per_page
-
- try:
- page = int(request.GET.get('page', '1'))
- 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"
-
- # check if request is from tagged questions
- if unanswered:
- # check if request is from unanswered questions
- # Article.objects.filter(publications__id__exact=1)
- objects = Question.objects.filter(book__id__exact=book.id, deleted=False, answer_count=0).order_by(orderby)
- else:
- objects = Question.objects.filter(book__id__exact=book.id, deleted=False).order_by(orderby)
-
- # RISK - inner join queries
- objects = objects.select_related();
- objects_list = Paginator(objects, user_page_size)
- questions = objects_list.page(page)
-
- return render_to_response('book.html', {
- "book" : book,
- "author_info" : author_info,
- "author_rss" : author_rss,
- "questions" : questions,
- "context" : {
- 'is_paginated' : True,
- 'pages': objects_list.num_pages,
- 'page': page,
- 'has_previous': questions.has_previous(),
- 'has_next': questions.has_next(),
- 'previous': questions.previous_page_number(),
- 'next': questions.next_page_number(),
- 'base_url' : request.path + '?sort=%s&' % view_id,
- 'pagesize' : user_page_size
- }
- }, context_instance=RequestContext(request))
-
-@login_required
-def ask_book(request, short_name):
- if request.method == "POST":
- form = AskForm(request.POST)
- if form.is_valid():
- added_at = datetime.datetime.now()
- html = sanitize_html(markdowner.convert(form.cleaned_data['text']))
- question = Question(
- title = strip_tags(form.cleaned_data['title']),
- author = request.user,
- added_at = added_at,
- last_activity_at = added_at,
- last_activity_by = request.user,
- wiki = form.cleaned_data['wiki'],
- tagnames = form.cleaned_data['tags'].strip(),
- html = html,
- summary = strip_tags(html)[:120]
- )
- if question.wiki:
- question.last_edited_by = question.author
- question.last_edited_at = added_at
- question.wikified_at = added_at
-
- question.save()
-
- # create the first revision
- QuestionRevision.objects.create(
- question = question,
- revision = 1,
- title = question.title,
- author = request.user,
- revised_at = added_at,
- tagnames = question.tagnames,
- summary = CONST['default_version'],
- text = form.cleaned_data['text']
- )
-
- books = Book.objects.extra(where=['short_name = %s'], params=[short_name])
- match_count = len(books)
- if match_count == 1:
- # the book info
- book = books[0]
- book.questions.add(question)
-
- return HttpResponseRedirect(question.get_absolute_url())
- else:
- form = AskForm()
-
- tags = _get_tags_cache_json()
- return render_to_response('ask.html', {
- 'form' : form,
- 'tags' : tags,
- }, context_instance=RequestContext(request))
-
-def search(request):
- """
- Search by question, user and tag keywords.
- For questions now we only search keywords in question title.
- """
- if request.method == "GET":
- keywords = request.GET.get("q")
- search_type = request.GET.get("t")
- try:
- page = int(request.GET.get('page', '1'))
- except ValueError:
- page = 1
- if keywords is None:
- return HttpResponseRedirect('/')
- if search_type == 'tag':
- return HttpResponseRedirect('/tags/?q=%s&page=%s' % (keywords.strip(), page))
- elif search_type == "user":
- return HttpResponseRedirect('/users/?q=%s&page=%s' % (keywords.strip(), page))
- elif search_type == "question":
-
- template_file = "questions.html"
- # Set flag to False by default. If it is equal to True, then need to be saved.
- pagesize_changed = False
- # get pagesize from session, if failed then get default value
- user_page_size = request.session.get("pagesize", QUESTIONS_PAGE_SIZE)
- # set pagesize equal to logon user specified value in database
- if request.user.is_authenticated() and request.user.questions_per_page > 0:
- user_page_size = request.user.questions_per_page
-
- try:
- page = int(request.GET.get('page', '1'))
- # get new pagesize from UI selection
- pagesize = int(request.GET.get('pagesize', user_page_size))
- if pagesize <> user_page_size:
- pagesize_changed = True
-
- except ValueError:
- page = 1
- pagesize = user_page_size
-
- # save this pagesize to user database
- if pagesize_changed:
- request.session["pagesize"] = pagesize
- if request.user.is_authenticated():
- user = request.user
- user.questions_per_page = pagesize
- user.save()
-
- 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"
-
- objects = Question.objects.filter(deleted=False).extra(where=['title like %s'], params=['%' + keywords + '%']).order_by(orderby)
-
- # RISK - inner join queries
- objects = objects.select_related();
- objects_list = Paginator(objects, pagesize)
- questions = objects_list.page(page)
-
- # Get related tags from this page objects
- related_tags = []
- for question in questions.object_list:
- tags = list(question.tags.all())
- for tag in tags:
- if tag not in related_tags:
- related_tags.append(tag)
-
- return render_to_response(template_file, {
- "questions" : questions,
- "tab_id" : view_id,
- "questions_count" : objects_list.count,
- "tags" : related_tags,
- "searchtag" : None,
- "searchtitle" : keywords,
- "keywords" : keywords,
- "is_unanswered" : False,
- "context" : {
- 'is_paginated' : True,
- 'pages': objects_list.num_pages,
- 'page': page,
- 'has_previous': questions.has_previous(),
- 'has_next': questions.has_next(),
- 'previous': questions.previous_page_number(),
- 'next': questions.next_page_number(),
- 'base_url' : request.path + '?t=question&q=%s&sort=%s&' % (keywords, view_id),
- 'pagesize' : pagesize
- }}, context_instance=RequestContext(request))
-
- else:
- raise Http404
-
+# encoding:utf-8
+import os.path
+import time, datetime, calendar, random
+import logging
+from urllib import quote, unquote
+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.core.paginator import Paginator, EmptyPage, InvalidPage
+from django.template import RequestContext
+from django.utils.html import *
+from django.utils import simplejson
+from django.core import serializers
+from django.db import transaction
+from django.contrib.contenttypes.models import ContentType
+from django.utils.translation import ugettext as _
+
+from utils.html import sanitize_html
+from markdown2 import Markdown
+#from lxml.html.diff import htmldiff
+from forum.diff import textDiff as htmldiff
+from forum.forms import *
+from forum.models import *
+from forum.auth import *
+from forum.const import *
+from forum.user import *
+from forum import auth
+
+# used in index page
+INDEX_PAGE_SIZE = 20
+INDEX_AWARD_SIZE = 15
+INDEX_TAGS_SIZE = 100
+# used in tags list
+DEFAULT_PAGE_SIZE = 60
+# used in questions
+QUESTIONS_PAGE_SIZE = 10
+# used in users
+USERS_PAGE_SIZE = 35
+# used in answers
+ANSWERS_PAGE_SIZE = 10
+markdowner = Markdown(html4tags=True)
+question_type = ContentType.objects.get_for_model(Question)
+answer_type = ContentType.objects.get_for_model(Answer)
+comment_type = ContentType.objects.get_for_model(Comment)
+question_revision_type = ContentType.objects.get_for_model(QuestionRevision)
+answer_revision_type = ContentType.objects.get_for_model(AnswerRevision)
+repute_type =ContentType.objects.get_for_model(Repute)
+question_type_id = question_type.id
+answer_type_id = answer_type.id
+comment_type_id = comment_type.id
+question_revision_type_id = question_revision_type.id
+answer_revision_type_id = answer_revision_type.id
+repute_type_id = repute_type.id
+def _get_tags_cache_json():
+ tags = Tag.objects.filter(deleted=False).all()
+ tags_list = []
+ for tag in tags:
+ dic = {'n': tag.name, 'c': tag.used_count }
+ tags_list.append(dic)
+ tags = simplejson.dumps(tags_list)
+ return tags
+
+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)
+ # RISK - inner join queries
+ questions = questions.select_related()
+ tags = Tag.objects.get_valid_tags(INDEX_TAGS_SIZE)
+
+ awards = Award.objects.get_recent_awards()
+
+ return render_to_response('index.html', {
+ "questions" : questions,
+ "tab_id" : view_id,
+ "tags" : tags,
+ "awards" : awards[:INDEX_AWARD_SIZE],
+ }, context_instance=RequestContext(request))
+
+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))
+
+def privacy(request):
+ return render_to_response('privacy.html', context_instance=RequestContext(request))
+
+def unanswered(request):
+ return questions(request, unanswered=True)
+
+def questions(request, tagname=None, unanswered=False):
+ """
+ List of Questions, Tagged questions, and Unanswered questions.
+ """
+ # template file
+ # "questions.html" or "unanswered.html"
+ template_file = "questions.html"
+ # Set flag to False by default. If it is equal to True, then need to be saved.
+ pagesize_changed = False
+ # get pagesize from session, if failed then get default value
+ pagesize = request.session.get("pagesize")
+ try:
+ page = int(request.GET.get('page', '1'))
+ 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"
+
+ # check if request is from tagged questions
+ if tagname is not None:
+ objects = Question.objects.get_questions_by_tag(tagname, orderby)
+ elif unanswered:
+ #check if request is from unanswered questions
+ template_file = "unanswered.html"
+ objects = Question.objects.get_unanswered_questions(orderby)
+ else:
+ objects = Question.objects.get_questions(orderby)
+
+ # RISK - inner join queries
+ objects = objects.select_related(depth=1);
+ objects_list = Paginator(objects, pagesize)
+ questions = objects_list.page(page)
+
+ # Get related tags from this page objects
+ if questions.object_list.count() > 0:
+ related_tags = Tag.objects.get_tags_by_questions(questions.object_list)
+ else:
+ related_tags = None
+ return render_to_response(template_file, {
+ "questions" : questions,
+ "tab_id" : view_id,
+ "questions_count" : objects_list.count,
+ "tags" : related_tags,
+ "searchtag" : tagname,
+ "is_unanswered" : unanswered,
+ "context" : {
+ 'is_paginated' : True,
+ 'pages': objects_list.num_pages,
+ 'page': page,
+ 'has_previous': questions.has_previous(),
+ 'has_next': questions.has_next(),
+ 'previous': questions.previous_page_number(),
+ 'next': questions.next_page_number(),
+ 'base_url' : request.path + '?sort=%s&' % view_id,
+ 'pagesize' : pagesize
+ }}, context_instance=RequestContext(request))
+
+#TODO: allow anynomus user to ask question by providing email and username.
+@login_required
+def ask(request):
+ if request.method == "POST":
+ form = AskForm(request.POST)
+ if form.is_valid():
+ added_at = datetime.datetime.now()
+ html = sanitize_html(markdowner.convert(form.cleaned_data['text']))
+ question = Question(
+ title = strip_tags(form.cleaned_data['title']),
+ author = request.user,
+ added_at = added_at,
+ last_activity_at = added_at,
+ last_activity_by = request.user,
+ wiki = form.cleaned_data['wiki'],
+ tagnames = form.cleaned_data['tags'].strip(),
+ html = html,
+ summary = strip_tags(html)[:120]
+ )
+ if question.wiki:
+ question.last_edited_by = question.author
+ question.last_edited_at = added_at
+ question.wikified_at = added_at
+
+ question.save()
+
+ # create the first revision
+ QuestionRevision.objects.create(
+ question = question,
+ revision = 1,
+ title = question.title,
+ author = request.user,
+ revised_at = added_at,
+ tagnames = question.tagnames,
+ summary = CONST['default_version'],
+ text = form.cleaned_data['text']
+ )
+
+ return HttpResponseRedirect(question.get_absolute_url())
+
+ else:
+ form = AskForm()
+
+ tags = _get_tags_cache_json()
+ return render_to_response('ask.html', {
+ 'form' : form,
+ 'tags' : tags,
+ }, context_instance=RequestContext(request))
+
+def question(request, id):
+ try:
+ page = int(request.GET.get('page', '1'))
+ except ValueError:
+ page = 1
+ view_id = request.GET.get('sort', 'votes')
+ view_dic = {"latest":"-added_at", "oldest":"added_at", "votes":"-score" }
+ try:
+ orderby = view_dic[view_id]
+ except KeyError:
+ view_id = "votes"
+ orderby = "-score"
+
+ question = get_object_or_404(Question, id=id)
+ if question.deleted and not can_view_deleted_post(request.user, question):
+ raise Http404
+ answer_form = AnswerForm(question)
+ answers = Answer.objects.get_answers_from_question(question, request.user)
+ answers = answers.select_related(depth=1)
+
+ favorited = question.has_favorite_by_user(request.user)
+ question_vote = question.votes.select_related().filter(user=request.user)
+ if question_vote is not None and question_vote.count() > 0:
+ question_vote = question_vote[0]
+
+ user_answer_votes = {}
+ for answer in answers:
+ vote = answer.get_user_vote(request.user)
+ if vote is not None and not user_answer_votes.has_key(answer.id):
+ vote_value = -1
+ if vote.is_upvote():
+ vote_value = 1
+ user_answer_votes[answer.id] = vote_value
+
+
+ if answers is not None:
+ answers = answers.order_by("-accepted", orderby)
+ objects_list = Paginator(answers, ANSWERS_PAGE_SIZE)
+ page_objects = objects_list.page(page)
+ # update view count
+ Question.objects.update_view_count(question)
+ return render_to_response('question.html', {
+ "question" : question,
+ "question_vote" : question_vote,
+ "question_comment_count":question.comments.count(),
+ "answer" : answer_form,
+ "answers" : page_objects.object_list,
+ "user_answer_votes": user_answer_votes,
+ "tags" : question.tags.all(),
+ "tab_id" : view_id,
+ "favorited" : favorited,
+ "similar_questions" : Question.objects.get_similar_questions(question),
+ "context" : {
+ 'is_paginated' : True,
+ 'pages': objects_list.num_pages,
+ 'page': page,
+ 'has_previous': page_objects.has_previous(),
+ 'has_next': page_objects.has_next(),
+ 'previous': page_objects.previous_page_number(),
+ 'next': page_objects.next_page_number(),
+ 'base_url' : request.path + '?sort=%s&' % view_id,
+ 'extend_url' : "#sort-top"
+ }
+ }, context_instance=RequestContext(request))
+
+@login_required
+def close(request, id):
+ question = get_object_or_404(Question, id=id)
+ if not can_close_question(request.user, question):
+ return HttpResponse('Permission denied.')
+ if request.method == 'POST':
+ form = CloseForm(request.POST)
+ if form.is_valid():
+ reason = form.cleaned_data['reason']
+ question.closed = True
+ question.closed_by = request.user
+ question.closed_at = datetime.datetime.now()
+ question.close_reason = reason
+ question.save()
+ return HttpResponseRedirect(question.get_absolute_url())
+ else:
+ form = CloseForm()
+ return render_to_response('close.html', {
+ 'form' : form,
+ 'question' : question,
+ }, context_instance=RequestContext(request))
+
+@login_required
+def reopen(request, id):
+ question = get_object_or_404(Question, id=id)
+ # open question
+ if not can_reopen_question(request.user, question):
+ return HttpResponse('Permission denied.')
+ if request.method == 'POST' :
+ Question.objects.filter(id=question.id).update(closed=False,
+ closed_by=None, closed_at=None, close_reason=None)
+ return HttpResponseRedirect(question.get_absolute_url())
+ else:
+ return render_to_response('reopen.html', {
+ 'question' : question,
+ }, context_instance=RequestContext(request))
+
+@login_required
+def edit_question(request, id):
+ question = get_object_or_404(Question, id=id)
+ if question.deleted and not can_view_deleted_post(request.user, question):
+ raise Http404
+ if can_edit_post(request.user, question):
+ return _edit_question(request, question)
+ elif can_retag_questions(request.user):
+ return _retag_question(request, question)
+ else:
+ raise Http404
+
+def _retag_question(request, question):
+ if request.method == 'POST':
+ form = RetagQuestionForm(question, request.POST)
+ if form.is_valid():
+ if form.has_changed():
+ latest_revision = question.get_latest_revision()
+ retagged_at = datetime.datetime.now()
+ # Update the Question itself
+ Question.objects.filter(id=question.id).update(
+ tagnames = form.cleaned_data['tags'],
+ last_edited_at = retagged_at,
+ last_edited_by = request.user,
+ last_activity_at = retagged_at,
+ last_activity_by = request.user
+ )
+ # Update the Question's tag associations
+ tags_updated = Question.objects.update_tags(question,
+ form.cleaned_data['tags'], request.user)
+ # Create a new revision
+ QuestionRevision.objects.create(
+ question = question,
+ title = latest_revision.title,
+ author = request.user,
+ revised_at = retagged_at,
+ tagnames = form.cleaned_data['tags'],
+ summary = CONST['retagged'],
+ text = latest_revision.text
+ )
+ # send tags updated singal
+ tags_updated.send(sender=question.__class__, question=question)
+
+ return HttpResponseRedirect(question.get_absolute_url())
+ else:
+ form = RetagQuestionForm(question)
+ return render_to_response('question_retag.html', {
+ 'question': question,
+ 'form' : form,
+ 'tags' : _get_tags_cache_json(),
+ }, context_instance=RequestContext(request))
+
+
+def _edit_question(request, question):
+ latest_revision = question.get_latest_revision()
+ revision_form = None
+ if request.method == 'POST':
+ if 'select_revision' in request.POST:
+ # user has changed revistion number
+ revision_form = RevisionForm(question, latest_revision, request.POST)
+ if revision_form.is_valid():
+ # Replace with those from the selected revision
+ form = EditQuestionForm(question,
+ QuestionRevision.objects.get(question=question,
+ revision=revision_form.cleaned_data['revision']))
+ else:
+ form = EditQuestionForm(question, latest_revision, request.POST)
+ else:
+ # Always check modifications against the latest revision
+ form = EditQuestionForm(question, latest_revision, request.POST)
+ if form.is_valid():
+ html = sanitize_html(markdowner.convert(form.cleaned_data['text']))
+ if form.has_changed():
+ edited_at = datetime.datetime.now()
+ tags_changed = (latest_revision.tagnames !=
+ form.cleaned_data['tags'])
+ tags_updated = False
+ # Update the Question itself
+ updated_fields = {
+ 'title': form.cleaned_data['title'],
+ 'last_edited_at': edited_at,
+ 'last_edited_by': request.user,
+ 'last_activity_at': edited_at,
+ 'last_activity_by': request.user,
+ 'tagnames': form.cleaned_data['tags'],
+ 'summary': strip_tags(html)[:120],
+ 'html': html,
+ }
+
+ # only save when it's checked
+ # because wiki doesn't allow to be edited if last version has been enabled already
+ # and we make sure this in forms.
+ if ('wiki' in form.cleaned_data and
+ form.cleaned_data['wiki']):
+ updated_fields['wiki'] = True
+ updated_fields['wikified_at'] = edited_at
+
+ Question.objects.filter(
+ id=question.id).update(**updated_fields)
+ # Update the Question's tag associations
+ if tags_changed:
+ tags_updated = Question.objects.update_tags(
+ question, form.cleaned_data['tags'], request.user)
+ # Create a new revision
+ revision = QuestionRevision(
+ question = question,
+ title = form.cleaned_data['title'],
+ author = request.user,
+ revised_at = edited_at,
+ tagnames = form.cleaned_data['tags'],
+ text = form.cleaned_data['text'],
+ )
+ if form.cleaned_data['summary']:
+ revision.summary = form.cleaned_data['summary']
+ else:
+ revision.summary = 'No.%s Revision' % latest_revision.revision
+ revision.save()
+
+ return HttpResponseRedirect(question.get_absolute_url())
+ else:
+
+ revision_form = RevisionForm(question, latest_revision)
+ form = EditQuestionForm(question, latest_revision)
+ return render_to_response('question_edit.html', {
+ 'question': question,
+ 'revision_form': revision_form,
+ 'form' : form,
+ 'tags' : _get_tags_cache_json()
+ }, context_instance=RequestContext(request))
+
+
+@login_required
+def edit_answer(request, id):
+ answer = get_object_or_404(Answer, id=id)
+ if answer.deleted and not can_view_deleted_post(request.user, answer):
+ raise Http404
+ elif not can_edit_post(request.user, answer):
+ raise Http404
+ else:
+ latest_revision = answer.get_latest_revision()
+ if request.method == "POST":
+ if 'select_revision' in request.POST:
+ # user has changed revistion number
+ revision_form = RevisionForm(answer, latest_revision, request.POST)
+ if revision_form.is_valid():
+ # Replace with those from the selected revision
+ form = EditAnswerForm(answer,
+ AnswerRevision.objects.get(answer=answer,
+ revision=revision_form.cleaned_data['revision']))
+ else:
+ form = EditAnswerForm(answer, latest_revision, request.POST)
+ else:
+ form = EditAnswerForm(answer, latest_revision, request.POST)
+ if form.is_valid():
+ html = sanitize_html(markdowner.convert(form.cleaned_data['text']))
+ if form.has_changed():
+ edited_at = datetime.datetime.now()
+ updated_fields = {
+ 'last_edited_at': edited_at,
+ 'last_edited_by': request.user,
+ 'html': html,
+ }
+ Answer.objects.filter(id=answer.id).update(**updated_fields)
+
+ revision = AnswerRevision(
+ answer = answer,
+ author = request.user,
+ revised_at = edited_at,
+ text = form.cleaned_data['text']
+ )
+
+ if form.cleaned_data['summary']:
+ revision.summary = form.cleaned_data['summary']
+ else:
+ revision.summary = 'No.%s Revision' % latest_revision.revision
+ revision.save()
+
+ answer.question.last_activity_at = edited_at
+ answer.question.last_activity_by = request.user
+ answer.question.save()
+
+ return HttpResponseRedirect(answer.get_absolute_url())
+ else:
+ revision_form = RevisionForm(answer, latest_revision)
+ form = EditAnswerForm(answer, latest_revision)
+ return render_to_response('answer_edit.html', {
+ 'answer': answer,
+ 'revision_form': revision_form,
+ 'form' : form,
+ }, context_instance=RequestContext(request))
+
+QUESTION_REVISION_TEMPLATE = ('<h1>%(title)s</h1>\n'
+ '<div class="text">%(html)s</div>\n'
+ '<div class="tags">%(tags)s</div>')
+def question_revisions(request, id):
+ post = get_object_or_404(Question, id=id)
+ revisions = list(post.revisions.all())
+ for i, revision in enumerate(revisions):
+ revision.html = QUESTION_REVISION_TEMPLATE % {
+ 'title': revision.title,
+ 'html': sanitize_html(markdowner.convert(revision.text)),
+ 'tags': ' '.join(['<a class="post-tag">%s</a>' % tag
+ for tag in revision.tagnames.split(' ')]),
+ }
+ if i > 0:
+ revisions[i - 1].diff = htmldiff(revision.html,
+ revisions[i - 1].html)
+ else:
+ revisions[i - 1].diff = QUESTION_REVISION_TEMPLATE % {
+ 'title': revisions[0].title,
+ 'html': sanitize_html(markdowner.convert(revisions[0].text)),
+ 'tags': ' '.join(['<a class="post-tag">%s</a>' % tag
+ for tag in revisions[0].tagnames.split(' ')]),
+ }
+ revisions[i - 1].summary = None
+ return render_to_response('revisions_question.html', {
+ 'post': post,
+ 'revisions': revisions,
+ }, context_instance=RequestContext(request))
+
+ANSWER_REVISION_TEMPLATE = ('<div class="text">%(html)s</div>')
+def answer_revisions(request, id):
+ post = get_object_or_404(Answer, id=id)
+ revisions = list(post.revisions.all())
+ 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)
+ else:
+ revisions[i - 1].diff = revisions[i-1].text
+ revisions[i - 1].summary = None
+ return render_to_response('revisions_answer.html', {
+ 'post': post,
+ 'revisions': revisions,
+ }, context_instance=RequestContext(request))
+
+#TODO: allow anynomus
+@login_required
+def answer(request, id):
+ question = get_object_or_404(Question, id=id)
+ if request.method == "POST":
+ form = AnswerForm(question, request.POST)
+ if form.is_valid():
+ update_time = datetime.datetime.now()
+ answer = Answer(
+ question = question,
+ author = request.user,
+ added_at = update_time,
+ wiki = form.cleaned_data['wiki'],
+ html = sanitize_html(markdowner.convert(form.cleaned_data['text'])),
+ )
+ if answer.wiki:
+ answer.last_edited_by = answer.author
+ answer.last_edited_at = update_time
+ answer.wikified_at = update_time
+
+ answer.save()
+ Question.objects.update_answer_count(question)
+
+ question = get_object_or_404(Question, id=id)
+ question.last_activity_at = update_time
+ question.last_activity_by = request.user
+ question.save()
+
+ AnswerRevision.objects.create(
+ answer = answer,
+ revision = 1,
+ author = request.user,
+ revised_at = update_time,
+ summary = CONST['default_version'],
+ text = form.cleaned_data['text']
+ )
+
+ return HttpResponseRedirect(question.get_absolute_url())
+
+def tags(request):
+ stag = ""
+ is_paginated = True
+ sortby = request.GET.get('sort', 'used')
+ try:
+ page = int(request.GET.get('page', '1'))
+ except ValueError:
+ page = 1
+
+ if request.method == "GET":
+ stag = request.GET.get("q", "").strip()
+ if stag is not None:
+ 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":
+ objects_list = Paginator(Tag.objects.all().filter(deleted=False).exclude(used_count=0).order_by("name"), DEFAULT_PAGE_SIZE)
+ else:
+ objects_list = Paginator(Tag.objects.all().filter(deleted=False).exclude(used_count=0).order_by("-used_count"), DEFAULT_PAGE_SIZE)
+
+ try:
+ tags = objects_list.page(page)
+ except (EmptyPage, InvalidPage):
+ tags = objects_list.page(objects_list.num_pages)
+
+ return render_to_response('tags.html', {
+ "tags" : tags,
+ "stag" : stag,
+ "tab_id" : sortby,
+ "keywords" : stag,
+ "context" : {
+ 'is_paginated' : is_paginated,
+ 'pages': objects_list.num_pages,
+ 'page': page,
+ 'has_previous': tags.has_previous(),
+ 'has_next': tags.has_next(),
+ 'previous': tags.previous_page_number(),
+ 'next': tags.next_page_number(),
+ 'base_url' : '/tags/?sort=%s&' % sortby
+ }
+
+ }, context_instance=RequestContext(request))
+
+def tag(request, tag):
+ return questions(request, tagname=tag)
+
+def vote(request, id):
+ """
+ vote_type:
+ acceptAnswer : 0,
+ questionUpVote : 1,
+ questionDownVote : 2,
+ favorite : 4,
+ answerUpVote: 5,
+ answerDownVote:6,
+ offensiveQuestion : 7,
+ offensiveAnswer:8,
+ removeQuestion: 9,
+ removeAnswer:10
+
+ accept answer code:
+ response_data['allowed'] = -1, Accept his own answer 0, no allowed - Anonymous 1, Allowed - by default
+ response_data['success'] = 0, failed 1, Success - by default
+ response_data['status'] = 0, By default 1, Answer has been accepted already(Cancel)
+
+ vote code:
+ allowed = -3, Don't have enough votes left
+ -2, Don't have enough reputation score
+ -1, Vote his own post
+ 0, no allowed - Anonymous
+ 1, Allowed - by default
+ status = 0, By default
+ 1, Cancel
+ 2, Vote is too old to be canceled
+
+ offensive code:
+ allowed = -3, Don't have enough flags left
+ -2, Don't have enough reputation score to do this
+ 0, not allowed
+ 1, allowed
+ status = 0, by default
+ 1, can't do it again
+ """
+ response_data = {
+ "allowed": 1,
+ "success": 1,
+ "status" : 0,
+ "count" : 0,
+ "message" : ''
+ }
+
+ def can_vote(vote_score, user):
+ if vote_score == 1:
+ return can_vote_up(request.user)
+ else:
+ return can_vote_down(request.user)
+
+ try:
+ if not request.user.is_authenticated():
+ response_data['allowed'] = 0
+ response_data['success'] = 0
+
+ elif request.is_ajax():
+ question = get_object_or_404(Question, id=id)
+ vote_type = request.POST.get('type')
+
+ #accept answer
+ if vote_type == '0':
+ answer_id = request.POST.get('postId')
+ answer = get_object_or_404(Answer, id=answer_id)
+ # make sure question author is current user
+ if question.author == request.user:
+ # answer user who is also question author is not allow to accept answer
+ if answer.author == question.author:
+ response_data['success'] = 0
+ response_data['allowed'] = -1
+ # check if answer has been accepted already
+ elif answer.accepted:
+ onAnswerAcceptCanceled(answer, request.user)
+ response_data['status'] = 1
+ else:
+ # set other answers in this question not accepted first
+ for answer_of_question in Answer.objects.get_answers_from_question(question, request.user):
+ if answer_of_question != answer and answer_of_question.accepted:
+ onAnswerAcceptCanceled(answer_of_question, request.user)
+
+ #make sure retrieve data again after above author changes, they may have related data
+ answer = get_object_or_404(Answer, id=answer_id)
+ onAnswerAccept(answer, request.user)
+ else:
+ response_data['allowed'] = 0
+ response_data['success'] = 0
+ # favorite
+ elif vote_type == '4':
+ has_favorited = False
+ fav_questions = FavoriteQuestion.objects.filter(question=question)
+ # if the same question has been favorited before, then delete it
+ if fav_questions is not None:
+ for item in fav_questions:
+ if item.user == request.user:
+ item.delete()
+ response_data['status'] = 1
+ response_data['count'] = len(fav_questions) - 1
+ if response_data['count'] < 0:
+ response_data['count'] = 0
+ has_favorited = True
+ # if above deletion has not been executed, just insert a new favorite question
+ if not has_favorited:
+ new_item = FavoriteQuestion(question=question, user=request.user)
+ new_item.save()
+ response_data['count'] = FavoriteQuestion.objects.filter(question=question).count()
+ Question.objects.update_favorite_count(question)
+
+ elif vote_type in ['1', '2', '5', '6']:
+ post_id = id
+ post = question
+ vote_score = 1
+ if vote_type in ['5', '6']:
+ answer_id = request.POST.get('postId')
+ answer = get_object_or_404(Answer, id=answer_id)
+ post_id = answer_id
+ post = answer
+ if vote_type in ['2', '6']:
+ vote_score = -1
+
+ if post.author == request.user:
+ response_data['allowed'] = -1
+ elif not can_vote(vote_score, request.user):
+ response_data['allowed'] = -2
+ elif post.votes.filter(user=request.user).count() > 0:
+ vote = post.votes.filter(user=request.user)[0]
+ # unvote should be less than certain time
+ if (datetime.datetime.now().day - vote.voted_at.day) >= VOTE_RULES['scope_deny_unvote_days']:
+ response_data['status'] = 2
+ else:
+ voted = vote.vote
+ if voted > 0:
+ # cancel upvote
+ onUpVotedCanceled(vote, post, request.user)
+
+ else:
+ # cancel downvote
+ onDownVotedCanceled(vote, post, request.user)
+
+ response_data['status'] = 1
+ response_data['count'] = post.score
+ elif Vote.objects.get_votes_count_today_from_user(request.user) >= VOTE_RULES['scope_votes_per_user_per_day']:
+ response_data['allowed'] = -3
+ else:
+ vote = Vote(user=request.user, content_object=post, vote=vote_score, voted_at=datetime.datetime.now())
+ if vote_score > 0:
+ # upvote
+ onUpVoted(vote, post, request.user)
+ else:
+ # downvote
+ onDownVoted(vote, post, request.user)
+
+ votes_left = VOTE_RULES['scope_votes_per_user_per_day'] - Vote.objects.get_votes_count_today_from_user(request.user)
+ if votes_left <= VOTE_RULES['scope_warn_votes_left']:
+ response_data['message'] = u'%s votes left' % votes_left
+ response_data['count'] = post.score
+ elif vote_type in ['7', '8']:
+ post = question
+ post_id = id
+ if vote_type == '8':
+ post_id = request.POST.get('postId')
+ post = get_object_or_404(Answer, id=post_id)
+
+ if FlaggedItem.objects.get_flagged_items_count_today(request.user) >= VOTE_RULES['scope_flags_per_user_per_day']:
+ response_data['allowed'] = -3
+ elif not can_flag_offensive(request.user):
+ response_data['allowed'] = -2
+ elif post.flagged_items.filter(user=request.user).count() > 0:
+ response_data['status'] = 1
+ else:
+ item = FlaggedItem(user=request.user, content_object=post, flagged_at=datetime.datetime.now())
+ onFlaggedItem(item, post, request.user)
+ response_data['count'] = post.offensive_flag_count
+ # send signal when question or answer be marked offensive
+ mark_offensive.send(sender=post.__class__, instance=post, mark_by=request.user)
+ elif vote_type in ['9', '10']:
+ post = question
+ post_id = id
+ if vote_type == '10':
+ post_id = request.POST.get('postId')
+ post = get_object_or_404(Answer, id=post_id)
+
+ if not can_delete_post(request.user, post):
+ response_data['allowed'] = -2
+ elif post.deleted:
+ onDeleteCanceled(post, request.user)
+ response_data['status'] = 1
+ else:
+ onDeleted(post, request.user)
+ delete_post_or_answer.send(sender=post.__class__, instance=post, delete_by=request.user)
+ else:
+ response_data['success'] = 0
+ response_data['message'] = u'Request mode is not supported. Please try again.'
+
+ data = simplejson.dumps(response_data)
+
+ except Exception, e:
+ response_data['message'] = str(e)
+ data = simplejson.dumps(response_data)
+ return HttpResponse(data, mimetype="application/json")
+
+def users(request):
+ is_paginated = True
+ sortby = request.GET.get('sort', 'reputation')
+ suser = request.REQUEST.get('q', "")
+ try:
+ page = int(request.GET.get('page', '1'))
+ except ValueError:
+ page = 1
+
+ if suser == "":
+ if sortby == "newest":
+ objects_list = Paginator(User.objects.all().order_by('-date_joined'), USERS_PAGE_SIZE)
+ elif sortby == "last":
+ objects_list = Paginator(User.objects.all().order_by('date_joined'), USERS_PAGE_SIZE)
+ elif sortby == "user":
+ objects_list = Paginator(User.objects.all().order_by('username'), USERS_PAGE_SIZE)
+ # default
+ else:
+ objects_list = Paginator(User.objects.all().order_by('-reputation'), USERS_PAGE_SIZE)
+ base_url = '/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 = '/users/?name=%s&sort=%s&' % (suser, sortby)
+
+ try:
+ users = objects_list.page(page)
+ except (EmptyPage, InvalidPage):
+ users = objects_list.page(objects_list.num_pages)
+
+ return render_to_response('users.html', {
+ "users" : users,
+ "suser" : suser,
+ "keywords" : suser,
+ "tab_id" : sortby,
+ "context" : {
+ 'is_paginated' : is_paginated,
+ 'pages': objects_list.num_pages,
+ 'page': page,
+ 'has_previous': users.has_previous(),
+ 'has_next': users.has_next(),
+ 'previous': users.previous_page_number(),
+ 'next': users.next_page_number(),
+ 'base_url' : base_url
+ }
+
+ }, context_instance=RequestContext(request))
+
+def user(request, id):
+ sort = request.GET.get('sort', 'stats')
+ user_view = dict((v.id, v) for v in USER_TEMPLATE_VIEWS).get(sort, USER_TEMPLATE_VIEWS[0])
+ from forum import views
+ func = getattr(views, user_view.view_name)
+ return func(request, id, user_view)
+
+@login_required
+def edit_user(request, id):
+ user = get_object_or_404(User, id=id)
+ if request.user != user:
+ raise Http404
+ if request.method == "POST":
+ form = EditUserForm(user, request.POST)
+ if form.is_valid():
+ user.email = sanitize_html(form.cleaned_data['email'])
+ user.real_name = sanitize_html(form.cleaned_data['realname'])
+ user.website = sanitize_html(form.cleaned_data['website'])
+ user.location = sanitize_html(form.cleaned_data['city'])
+ user.date_of_birth = sanitize_html(form.cleaned_data['birthday'])
+ if len(user.date_of_birth) == 0:
+ user.date_of_birth = '1900-01-01'
+ user.about = sanitize_html(form.cleaned_data['about'])
+
+ user.save()
+ # send user updated singal if full fields have been updated
+ if user.email and user.real_name and user.website and user.location and \
+ user.date_of_birth and user.about:
+ user_updated.send(sender=user.__class__, instance=user, updated_by=user)
+ return HttpResponseRedirect(user.get_profile_url())
+ else:
+ form = EditUserForm(user)
+ return render_to_response('user_edit.html', {
+ 'form' : form,
+ }, context_instance=RequestContext(request))
+
+def user_stats(request, user_id, user_view):
+ user = get_object_or_404(User, id=user_id)
+ questions = Question.objects.extra(
+ select={
+ 'vote_count' : 'question.score',
+ 'favorited_myself' : 'SELECT count(*) FROM favorite_question f WHERE f.user_id = %s AND f.question_id = question.id',
+ 'la_user_id' : 'auth_user.id',
+ 'la_username' : 'auth_user.username',
+ 'la_user_gold' : 'auth_user.gold',
+ 'la_user_silver' : 'auth_user.silver',
+ 'la_user_bronze' : 'auth_user.bronze',
+ 'la_user_reputation' : 'auth_user.reputation'
+ },
+ select_params=[user_id],
+ tables=['question', 'auth_user'],
+ where=['question.deleted = 0 AND question.author_id=%s AND question.last_activity_by_id = auth_user.id'],
+ params=[user_id],
+ order_by=['-vote_count', '-last_activity_at']
+ ).values('vote_count',
+ 'favorited_myself',
+ 'id',
+ 'title',
+ 'author_id',
+ 'added_at',
+ 'answer_accepted',
+ 'answer_count',
+ 'comment_count',
+ 'view_count',
+ 'favourite_count',
+ 'summary',
+ 'tagnames',
+ 'vote_up_count',
+ 'vote_down_count',
+ 'last_activity_at',
+ 'la_user_id',
+ 'la_username',
+ 'la_user_gold',
+ 'la_user_silver',
+ 'la_user_bronze',
+ 'la_user_reputation')[:100]
+
+ answered_questions = Question.objects.extra(
+ select={
+ 'vote_up_count' : 'answer.vote_up_count',
+ 'vote_down_count' : 'answer.vote_down_count',
+ 'answer_id' : 'answer.id',
+ 'accepted' : 'answer.accepted',
+ 'vote_count' : 'answer.score',
+ 'comment_count' : 'answer.comment_count'
+ },
+ tables=['question', 'answer'],
+ where=['answer.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]
+ ).distinct().values('comment_count',
+ 'id',
+ 'answer_id',
+ 'title',
+ 'author_id',
+ 'accepted',
+ 'vote_count',
+ 'answer_count',
+ 'vote_up_count',
+ 'vote_down_count')[:100]
+ up_votes = Vote.objects.get_up_vote_count_from_user(user)
+ down_votes = Vote.objects.get_down_vote_count_from_user(user)
+ votes_today = Vote.objects.get_votes_count_today_from_user(user)
+ votes_total = VOTE_RULES['scope_votes_per_user_per_day']
+ tags = user.created_tags.all().order_by('-used_count')[:50]
+ awards = Award.objects.extra(
+ select={'id': 'badge.id', 'count': 'count(badge_id)', 'name':'badge.name', 'description': 'badge.description', 'type': 'badge.type'},
+ tables=['award', 'badge'],
+ order_by=['-awarded_at'],
+ where=['user_id=%s AND badge_id=badge.id'],
+ params=[user.id]
+ ).values('id', 'count', 'name', 'description', 'type')
+ total_awards = awards.count()
+ awards.query.group_by = ['badge_id']
+
+ 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,
+ "questions" : questions,
+ "answered_questions" : answered_questions,
+ "up_votes" : up_votes,
+ "down_votes" : down_votes,
+ "total_votes": up_votes + down_votes,
+ "votes_today_left": votes_total-votes_today,
+ "votes_total_per_day": votes_total,
+ "tags" : tags,
+ "awards": awards,
+ "total_awards" : total_awards,
+ }, context_instance=RequestContext(request))
+
+def user_recent(request, user_id, user_view):
+ user = get_object_or_404(User, id=user_id)
+ def get_type_name(type_id):
+ for item in TYPE_ACTIVITY:
+ if type_id in item:
+ return item[1]
+
+ class Event:
+ def __init__(self, time, type, title, summary, answer_id, question_id):
+ self.time = time
+ self.type = get_type_name(type)
+ self.type_id = type
+ self.title = title
+ self.summary = summary
+ self.title_link = u'/questions/%s/%s#%s' %(question_id, title, answer_id)\
+ if int(answer_id) > 0 else u'/questions/%s/%s' %(question_id, title)
+ class AwardEvent:
+ def __init__(self, time, type, id):
+ self.time = time
+ self.type = get_type_name(type)
+ self.type_id = type
+ self.badge = get_object_or_404(Badge, id=id)
+
+ activities = []
+ # ask questions
+ questions = Activity.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'active_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type'
+ },
+ 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'],
+ params=[question_type_id, user_id, TYPE_ACTIVITY_ASK_QUESTION],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'active_at',
+ 'activity_type'
+ )
+ if len(questions) > 0:
+ questions = [(Event(q['active_at'], q['activity_type'], q['title'], '', '0', \
+ q['question_id'])) for q in questions]
+ activities.extend(questions)
+
+ # answers
+ answers = Activity.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'active_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type'
+ },
+ 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'],
+ params=[answer_type_id, user_id, TYPE_ACTIVITY_ANSWER],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'active_at',
+ 'activity_type'
+ )
+ if len(answers) > 0:
+ answers = [(Event(q['active_at'], q['activity_type'], q['title'], '', q['answer_id'], \
+ q['question_id'])) for q in answers]
+ activities.extend(answers)
+
+ # question comments
+ comments = Activity.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'comment.object_id',
+ 'added_at' : 'comment.added_at',
+ 'activity_type' : 'activity.activity_type'
+ },
+ tables=['activity', 'question', 'comment'],
+
+ 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'],
+ params=[comment_type_id, question_type_id, user_id, TYPE_ACTIVITY_COMMENT_QUESTION],
+ order_by=['-comment.added_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'activity_type'
+ )
+
+ if len(comments) > 0:
+ comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \
+ q['question_id'])) for q in comments]
+ activities.extend(comments)
+
+ # answer comments
+ comments = Activity.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'added_at' : 'comment.added_at',
+ 'activity_type' : 'activity.activity_type'
+ },
+ tables=['activity', 'question', 'answer', 'comment'],
+
+ 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'],
+ params=[comment_type_id, answer_type_id, user_id, TYPE_ACTIVITY_COMMENT_ANSWER],
+ order_by=['-comment.added_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'added_at',
+ 'activity_type'
+ )
+
+ if len(comments) > 0:
+ comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', q['answer_id'], \
+ q['question_id'])) for q in comments]
+ activities.extend(comments)
+
+ # question revisions
+ revisions = Activity.objects.extra(
+ select={
+ 'title' : 'question_revision.title',
+ 'question_id' : 'question_revision.question_id',
+ 'added_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type',
+ 'summary' : 'question_revision.summary'
+ },
+ tables=['activity', 'question_revision'],
+ where=['activity.content_type_id = %s AND activity.object_id = question_revision.id 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],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'activity_type',
+ 'summary'
+ )
+
+ if len(revisions) > 0:
+ revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], '0', \
+ q['question_id'])) for q in revisions]
+ activities.extend(revisions)
+
+ # answer revisions
+ revisions = Activity.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'added_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type',
+ 'summary' : 'answer_revision.summary'
+ },
+ tables=['activity', 'answer_revision', 'question', 'answer'],
+
+ 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 '+
+ 'activity.activity_type=%s'],
+ params=[answer_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_ANSWER],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'answer_id',
+ 'activity_type',
+ 'summary'
+ )
+
+ if len(revisions) > 0:
+ revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], \
+ q['answer_id'], q['question_id'])) for q in revisions]
+ activities.extend(revisions)
+
+ # accepted answers
+ accept_answers = Activity.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'added_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type',
+ },
+ 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.question_id=question.id AND activity.activity_type=%s'],
+ params=[answer_type_id, user_id, TYPE_ACTIVITY_MARK_ANSWER],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'activity_type',
+ )
+ if len(accept_answers) > 0:
+ accept_answers = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \
+ q['question_id'])) for q in accept_answers]
+ activities.extend(accept_answers)
+ #award history
+ awards = Activity.objects.extra(
+ select={
+ 'badge_id' : 'badge.id',
+ 'awarded_at': 'award.awarded_at',
+ 'activity_type' : 'activity.activity_type'
+ },
+ tables=['activity', 'award', 'badge'],
+ where=['activity.user_id = award.user_id AND activity.user_id = %s AND '+
+ 'award.badge_id=badge.id AND activity.object_id=award.id AND activity.activity_type=%s'],
+ params=[user_id, TYPE_ACTIVITY_PRIZE],
+ order_by=['-activity.active_at']
+ ).values(
+ 'badge_id',
+ 'awarded_at',
+ 'activity_type'
+ )
+ if len(awards) > 0:
+ awards = [(AwardEvent(q['awarded_at'], q['activity_type'], q['badge_id'])) for q in awards]
+ activities.extend(awards)
+
+ activities.sort(lambda x,y: cmp(y.time, x.time))
+
+ 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,
+ "activities" : activities[:user_view.data_size]
+ }, context_instance=RequestContext(request))
+
+def user_responses(request, user_id, user_view):
+ """
+ We list answers for question, comments, and answer accepted by others for this user.
+ """
+ class Response:
+ def __init__(self, type, title, question_id, answer_id, time, username, user_id, content):
+ self.type = type
+ self.title = title
+ self.titlelink = u'/questions/%s/%s#%s' % (question_id, title, answer_id)
+ self.time = time
+ self.userlink = u'/users/%s/%s/' % (user_id, username)
+ self.username = username
+ self.content = u'%s ...' % strip_tags(content)[:300]
+
+ def __unicode__(self):
+ return u'%s %s' % (self.type, self.titlelink)
+
+ user = get_object_or_404(User, id=user_id)
+ responses = []
+ answers = Answer.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'added_at' : 'answer.added_at',
+ 'html' : 'answer.html',
+ 'username' : 'auth_user.username',
+ 'user_id' : 'auth_user.id'
+ },
+ select_params=[user_id],
+ tables=['answer', 'question', 'auth_user'],
+ where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND '+
+ 'question.author_id = %s AND answer.author_id <> %s AND answer.author_id=auth_user.id'],
+ params=[user_id, user_id],
+ order_by=['-answer.id']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'added_at',
+ 'html',
+ 'username',
+ 'user_id'
+ )
+ if len(answers) > 0:
+ answers = [(Response(TYPE_RESPONSE['QUESTION_ANSWERED'], a['title'], a['question_id'],
+ a['answer_id'], a['added_at'], a['username'], a['user_id'], a['html'])) for a in answers]
+ responses.extend(answers)
+
+
+ # question comments
+ comments = Comment.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'comment.object_id',
+ 'added_at' : 'comment.added_at',
+ 'comment' : 'comment.comment',
+ 'username' : 'auth_user.username',
+ 'user_id' : 'auth_user.id'
+ },
+ tables=['question', 'auth_user', 'comment'],
+ where=['question.deleted = 0 AND question.author_id = %s AND comment.object_id=question.id AND '+
+ 'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id'],
+ params=[user_id, question_type_id, user_id],
+ order_by=['-comment.added_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'comment',
+ 'username',
+ 'user_id'
+ )
+
+ if len(comments) > 0:
+ comments = [(Response(TYPE_RESPONSE['QUESTION_COMMENTED'], c['title'], c['question_id'],
+ '', c['added_at'], c['username'], c['user_id'], c['comment'])) for c in comments]
+ responses.extend(comments)
+
+ # answer comments
+ comments = Comment.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'added_at' : 'comment.added_at',
+ 'comment' : 'comment.comment',
+ 'username' : 'auth_user.username',
+ 'user_id' : 'auth_user.id'
+ },
+ tables=['answer', 'auth_user', 'comment', 'question'],
+ where=['answer.deleted = 0 AND answer.author_id = %s AND comment.object_id=answer.id AND '+
+ 'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id '+
+ 'AND question.id = answer.question_id'],
+ params=[user_id, answer_type_id, user_id],
+ order_by=['-comment.added_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'added_at',
+ 'comment',
+ 'username',
+ 'user_id'
+ )
+
+ if len(comments) > 0:
+ comments = [(Response(TYPE_RESPONSE['ANSWER_COMMENTED'], c['title'], c['question_id'],
+ c['answer_id'], c['added_at'], c['username'], c['user_id'], c['comment'])) for c in comments]
+ responses.extend(comments)
+
+ # answer has been accepted
+ answers = Answer.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'added_at' : 'answer.accepted_at',
+ 'html' : 'answer.html',
+ 'username' : 'auth_user.username',
+ 'user_id' : 'auth_user.id'
+ },
+ select_params=[user_id],
+ tables=['answer', 'question', 'auth_user'],
+ where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND '+
+ 'answer.author_id = %s AND answer.accepted=1 AND question.author_id=auth_user.id'],
+ params=[user_id],
+ order_by=['-answer.id']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'added_at',
+ 'html',
+ 'username',
+ 'user_id'
+ )
+ if len(answers) > 0:
+ answers = [(Response(TYPE_RESPONSE['ANSWER_ACCEPTED'], a['title'], a['question_id'],
+ a['answer_id'], a['added_at'], a['username'], a['user_id'], a['html'])) for a in answers]
+ responses.extend(answers)
+
+ # sort posts by time
+ responses.sort(lambda x,y: cmp(y.time, x.time))
+
+ 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,
+ "responses" : responses[:user_view.data_size],
+
+ }, context_instance=RequestContext(request))
+
+def user_votes(request, user_id, user_view):
+ user = get_object_or_404(User, id=user_id)
+ if not can_view_user_votes(request.user, user):
+ raise Http404
+ votes = []
+ question_votes = Vote.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 0,
+ 'voted_at' : 'vote.voted_at',
+ 'vote' : 'vote',
+ },
+ select_params=[user_id],
+ tables=['vote', 'question', 'auth_user'],
+ where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = question.id '+
+ 'AND vote.user_id=auth_user.id'],
+ params=[question_type_id, user_id],
+ order_by=['-vote.id']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'voted_at',
+ 'vote',
+ )
+ if(len(question_votes) > 0):
+ votes.extend(question_votes)
+
+ answer_votes = Vote.objects.extra(
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'voted_at' : 'vote.voted_at',
+ 'vote' : 'vote',
+ },
+ select_params=[user_id],
+ tables=['vote', 'answer', 'question', 'auth_user'],
+ where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = answer.id '+
+ 'AND answer.question_id = question.id AND vote.user_id=auth_user.id'],
+ params=[answer_type_id, user_id],
+ order_by=['-vote.id']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'voted_at',
+ 'vote',
+ )
+ if(len(answer_votes) > 0):
+ votes.extend(answer_votes)
+ votes.sort(lambda x,y: cmp(y['voted_at'], x['voted_at']))
+ 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,
+ "votes" : votes[:user_view.data_size]
+
+ }, context_instance=RequestContext(request))
+
+def user_reputation(request, user_id, user_view):
+ user = get_object_or_404(User, id=user_id)
+ reputation = Repute.objects.extra(
+ select={'positive': 'sum(positive)', 'negative': 'sum(negative)', 'question_id':'question_id',
+ 'title': 'question.title'},
+ tables=['repute', 'question'],
+ order_by=['-reputed_at'],
+ where=['user_id=%s AND question_id=question.id'],
+ params=[user.id]
+ ).values('positive', 'negative', 'question_id', 'title', 'reputed_at', 'reputation')
+
+ reputation.query.group_by = ['question_id']
+
+
+ rep_list = []
+ for rep in Repute.objects.filter(user=user).order_by('reputed_at'):
+ dic = '[%s,%s]' % (calendar.timegm(rep.reputed_at.timetuple()) * 1000, rep.reputation)
+ rep_list.append(dic)
+ reps = ','.join(rep_list)
+ reps = '[%s]' % reps
+
+ 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,
+ "reputation" : reputation,
+ "reps" : reps
+ }, context_instance=RequestContext(request))
+
+def user_favorites(request, user_id, user_view):
+ user = get_object_or_404(User, id=user_id)
+ questions = Question.objects.extra(
+ select={
+ 'vote_count' : 'question.vote_up_count + question.vote_down_count',
+ 'favorited_myself' : 'SELECT count(*) FROM favorite_question f WHERE f.user_id = %s '+
+ 'AND f.question_id = question.id',
+ 'la_user_id' : 'auth_user.id',
+ 'la_username' : 'auth_user.username',
+ 'la_user_gold' : 'auth_user.gold',
+ 'la_user_silver' : 'auth_user.silver',
+ 'la_user_bronze' : 'auth_user.bronze',
+ 'la_user_reputation' : 'auth_user.reputation'
+ },
+ select_params=[user_id],
+ tables=['question', 'auth_user', 'favorite_question'],
+ where=['question.deleted = 0 AND question.last_activity_by_id = auth_user.id '+
+ 'AND favorite_question.question_id = question.id AND favorite_question.user_id = %s'],
+ params=[user_id],
+ order_by=['-vote_count', '-question.id']
+ ).values('vote_count',
+ 'favorited_myself',
+ 'id',
+ 'title',
+ 'author_id',
+ 'added_at',
+ 'answer_accepted',
+ 'answer_count',
+ 'comment_count',
+ 'view_count',
+ 'favourite_count',
+ 'summary',
+ 'tagnames',
+ 'vote_up_count',
+ 'vote_down_count',
+ 'last_activity_at',
+ 'la_user_id',
+ 'la_username',
+ 'la_user_gold',
+ 'la_user_silver',
+ 'la_user_bronze',
+ 'la_user_reputation')
+ 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,
+ "questions" : questions[:user_view.data_size],
+ "view_user" : user
+ }, context_instance=RequestContext(request))
+
+
+def user_preferences(request, user_id, user_view):
+ user = get_object_or_404(User, id=user_id)
+ 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,
+ }, 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)
+
+def answer_comments(request, id):
+ answer = get_object_or_404(Answer, id=id)
+ user = request.user
+ return __comments(request, answer, 'answer', user)
+
+def __comments(request, obj, type, user):
+ # only support get comments by ajax now
+ if request.is_ajax():
+ if request.method == "GET":
+ return __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)
+
+def __generate_comments_json(obj, type, user):
+ 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 = []
+ 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)
+ json_comments.append({"id" : comment.id,
+ "object_id" : obj.id,
+ "add_date" : comment.added_at.strftime('%Y-%m-%d'),
+ "text" : comment.comment,
+ "user_display_name" : comment_user.username,
+ "user_url" : "/users/%s/%s" % (comment_user.id, comment_user.username),
+ "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_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)
+
+def logout(request):
+ url = request.GET.get('next')
+ return render_to_response('logout.html', {
+ 'next' : url,
+ }, context_instance=RequestContext(request))
+
+def badges(request):
+ badges = Badge.objects.all().order_by('type')
+ my_badges = []
+ if request.user.is_authenticated():
+ my_badges = Award.objects.filter(user=request.user)
+ my_badges.query.group_by = ['badge_id']
+
+ return render_to_response('badges.html', {
+ 'badges' : badges,
+ 'mybadges' : my_badges,
+ }, context_instance=RequestContext(request))
+
+def badge(request, id):
+ badge = get_object_or_404(Badge, id=id)
+ awards = Award.objects.extra(
+ select={'id': 'auth_user.id',
+ 'name': 'auth_user.username',
+ 'rep':'auth_user.reputation',
+ 'gold': 'auth_user.gold',
+ 'silver': 'auth_user.silver',
+ 'bronze': 'auth_user.bronze'},
+ tables=['award', 'auth_user'],
+ where=['badge_id=%s AND user_id=auth_user.id'],
+ params=[id]
+ ).values('id').distinct()
+
+ return render_to_response('badge.html', {
+ 'awards' : awards,
+ 'badge' : badge,
+ }, context_instance=RequestContext(request))
+
+def read_message(request):
+ if request.method == "POST":
+ if request.POST['formdata'] == 'required':
+ request.session['message_silent'] = 1
+
+ if request.user.is_authenticated():
+ request.user.delete_messages()
+ return HttpResponse('')
+
+def upload(request):
+ class FileTypeNotAllow(Exception):
+ pass
+ class FileSizeNotAllow(Exception):
+ pass
+ class UploadPermissionNotAuthorized(Exception):
+ pass
+
+ #<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>
+ xml_template = "<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>"
+
+ try:
+ f = request.FILES['file-upload']
+ # check upload permission
+ if not can_upload_files(request.user):
+ raise UploadPermissionNotAuthorized
+
+ # check file type
+ file_name_suffix = os.path.splitext(f.name)[1].lower()
+ if not file_name_suffix in settings.ALLOW_FILE_TYPES:
+ raise FileTypeNotAllow
+
+ # genetate new file name
+ new_file_name = str(time.time()).replace('.', str(random.randint(0,100000))) + file_name_suffix
+ # use default storage to store file
+ default_storage.save(new_file_name, f)
+ # check file size
+ # byte
+ size = default_storage.size(new_file_name)
+ if size > settings.ALLOW_MAX_FILE_SIZE:
+ default_storage.delete(new_file_name)
+ raise FileSizeNotAllow
+
+ result = xml_template % ('Good', '', default_storage.url(new_file_name))
+ except UploadPermissionNotAuthorized:
+ result = xml_template % ('', _('uploading images is limited to users with >60 reputation points'), '')
+ except FileTypeNotAllow:
+ result = xml_template % ('', _("allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"), '')
+ except FileSizeNotAllow:
+ result = xml_template % ('', _("maximum upload file size is %sK") % settings.ALLOW_MAX_FILE_SIZE / 1024, '')
+ except Exception:
+ result = xml_template % ('', _('Error uploading file. Please contact the site administrator. Thank you. %s' % Exception), '')
+
+ return HttpResponse(result, mimetype="application/xml")
+
+def books(request):
+ return HttpResponseRedirect("/books/mysql-zhaoyang")
+
+def book(request, short_name, unanswered=False):
+ """
+ 1. questions list
+ 2. book info
+ 3. author info and blog rss items
+ """
+ """
+ List of Questions, Tagged questions, and Unanswered questions.
+ """
+ books = Book.objects.extra(where=['short_name = %s'], params=[short_name])
+ match_count = len(books)
+ if match_count == 0 :
+ raise Http404
+ else:
+ # the book info
+ book = books[0]
+ # get author info
+ author_info = BookAuthorInfo.objects.get(book=book)
+ # get author rss info
+ author_rss = BookAuthorRss.objects.filter(book=book)
+
+ # get pagesize from session, if failed then get default value
+ user_page_size = request.session.get("pagesize", QUESTIONS_PAGE_SIZE)
+ # set pagesize equal to logon user specified value in database
+ if request.user.is_authenticated() and request.user.questions_per_page > 0:
+ user_page_size = request.user.questions_per_page
+
+ try:
+ page = int(request.GET.get('page', '1'))
+ 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"
+
+ # check if request is from tagged questions
+ if unanswered:
+ # check if request is from unanswered questions
+ # Article.objects.filter(publications__id__exact=1)
+ objects = Question.objects.filter(book__id__exact=book.id, deleted=False, answer_count=0).order_by(orderby)
+ else:
+ objects = Question.objects.filter(book__id__exact=book.id, deleted=False).order_by(orderby)
+
+ # RISK - inner join queries
+ objects = objects.select_related();
+ objects_list = Paginator(objects, user_page_size)
+ questions = objects_list.page(page)
+
+ return render_to_response('book.html', {
+ "book" : book,
+ "author_info" : author_info,
+ "author_rss" : author_rss,
+ "questions" : questions,
+ "context" : {
+ 'is_paginated' : True,
+ 'pages': objects_list.num_pages,
+ 'page': page,
+ 'has_previous': questions.has_previous(),
+ 'has_next': questions.has_next(),
+ 'previous': questions.previous_page_number(),
+ 'next': questions.next_page_number(),
+ 'base_url' : request.path + '?sort=%s&' % view_id,
+ 'pagesize' : user_page_size
+ }
+ }, context_instance=RequestContext(request))
+
+@login_required
+def ask_book(request, short_name):
+ if request.method == "POST":
+ form = AskForm(request.POST)
+ if form.is_valid():
+ added_at = datetime.datetime.now()
+ html = sanitize_html(markdowner.convert(form.cleaned_data['text']))
+ question = Question(
+ title = strip_tags(form.cleaned_data['title']),
+ author = request.user,
+ added_at = added_at,
+ last_activity_at = added_at,
+ last_activity_by = request.user,
+ wiki = form.cleaned_data['wiki'],
+ tagnames = form.cleaned_data['tags'].strip(),
+ html = html,
+ summary = strip_tags(html)[:120]
+ )
+ if question.wiki:
+ question.last_edited_by = question.author
+ question.last_edited_at = added_at
+ question.wikified_at = added_at
+
+ question.save()
+
+ # create the first revision
+ QuestionRevision.objects.create(
+ question = question,
+ revision = 1,
+ title = question.title,
+ author = request.user,
+ revised_at = added_at,
+ tagnames = question.tagnames,
+ summary = CONST['default_version'],
+ text = form.cleaned_data['text']
+ )
+
+ books = Book.objects.extra(where=['short_name = %s'], params=[short_name])
+ match_count = len(books)
+ if match_count == 1:
+ # the book info
+ book = books[0]
+ book.questions.add(question)
+
+ return HttpResponseRedirect(question.get_absolute_url())
+ else:
+ form = AskForm()
+
+ tags = _get_tags_cache_json()
+ return render_to_response('ask.html', {
+ 'form' : form,
+ 'tags' : tags,
+ }, context_instance=RequestContext(request))
+
+def search(request):
+ """
+ Search by question, user and tag keywords.
+ For questions now we only search keywords in question title.
+ """
+ if request.method == "GET":
+ keywords = request.GET.get("q")
+ search_type = request.GET.get("t")
+ try:
+ page = int(request.GET.get('page', '1'))
+ except ValueError:
+ page = 1
+ if keywords is None:
+ return HttpResponseRedirect('/')
+ if search_type == 'tag':
+ return HttpResponseRedirect('/tags/?q=%s&page=%s' % (keywords.strip(), page))
+ elif search_type == "user":
+ return HttpResponseRedirect('/users/?q=%s&page=%s' % (keywords.strip(), page))
+ elif search_type == "question":
+
+ template_file = "questions.html"
+ # Set flag to False by default. If it is equal to True, then need to be saved.
+ pagesize_changed = False
+ # get pagesize from session, if failed then get default value
+ user_page_size = request.session.get("pagesize", QUESTIONS_PAGE_SIZE)
+ # set pagesize equal to logon user specified value in database
+ if request.user.is_authenticated() and request.user.questions_per_page > 0:
+ user_page_size = request.user.questions_per_page
+
+ try:
+ page = int(request.GET.get('page', '1'))
+ # get new pagesize from UI selection
+ pagesize = int(request.GET.get('pagesize', user_page_size))
+ if pagesize <> user_page_size:
+ pagesize_changed = True
+
+ except ValueError:
+ page = 1
+ pagesize = user_page_size
+
+ # save this pagesize to user database
+ if pagesize_changed:
+ request.session["pagesize"] = pagesize
+ if request.user.is_authenticated():
+ user = request.user
+ user.questions_per_page = pagesize
+ user.save()
+
+ 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"
+
+ objects = Question.objects.filter(deleted=False).extra(where=['title like %s'], params=['%' + keywords + '%']).order_by(orderby)
+
+ # RISK - inner join queries
+ objects = objects.select_related();
+ objects_list = Paginator(objects, pagesize)
+ questions = objects_list.page(page)
+
+ # Get related tags from this page objects
+ related_tags = []
+ for question in questions.object_list:
+ tags = list(question.tags.all())
+ for tag in tags:
+ if tag not in related_tags:
+ related_tags.append(tag)
+
+ return render_to_response(template_file, {
+ "questions" : questions,
+ "tab_id" : view_id,
+ "questions_count" : objects_list.count,
+ "tags" : related_tags,
+ "searchtag" : None,
+ "searchtitle" : keywords,
+ "keywords" : keywords,
+ "is_unanswered" : False,
+ "context" : {
+ 'is_paginated' : True,
+ 'pages': objects_list.num_pages,
+ 'page': page,
+ 'has_previous': questions.has_previous(),
+ 'has_next': questions.has_next(),
+ 'previous': questions.previous_page_number(),
+ 'next': questions.next_page_number(),
+ 'base_url' : request.path + '?t=question&q=%s&sort=%s&' % (keywords, view_id),
+ 'pagesize' : pagesize
+ }}, context_instance=RequestContext(request))
+
+ else:
+ raise Http404
+
diff --git a/junk b/junk
new file mode 100644
index 00000000..3f3226d6
--- /dev/null
+++ b/junk
@@ -0,0 +1,7 @@
+/branches/beta2/forum/feed.py r110 line 17:
+/branches/beta2/forum/feed.py r110 line 20:
+/branches/beta2/forum/forms.py r110 line 63:
+/branches/beta2/templates/question.html r120 line 237:
+/branches/beta2/templates/question.html r120 line 57:
+/branches/beta2/templates/question.html r120 line 456:
+/branches/beta2/forum/views.py r127 line 1088:
diff --git a/lanai.psproj b/lanai.psproj
new file mode 100644
index 00000000..7f44d7ff
--- /dev/null
+++ b/lanai.psproj
@@ -0,0 +1,557 @@
+[PyScripter]
+Version=1.9.9.3
+
+[Project]
+ClassName=TProjectRootNode
+StoreRelativePaths=FALSE
+ShowFileExtensions=FALSE
+
+[Project\ChildNodes]
+Count=2
+
+[Project\ChildNodes\Node0]
+ClassName=TProjectFilesNode
+
+[Project\ChildNodes\Node0\ChildNodes]
+Count=1
+
+[Project\ChildNodes\Node0\ChildNodes\Node0]
+ClassName=TProjectFolderNode
+Name=src
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes]
+Count=10
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0]
+ClassName=TProjectFolderNode
+Name=django_authopenid
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes]
+Count=9
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\django_authopenid\__init__.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\django_authopenid\admin.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\django_authopenid\forms.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\django_authopenid\middleware.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\django_authopenid\mimeparse.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node5]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\django_authopenid\models.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node6]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\django_authopenid\urls.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node7]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\django_authopenid\util.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node8]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\django_authopenid\views.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1]
+ClassName=TProjectFolderNode
+Name=forum
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes]
+Count=12
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0]
+ClassName=TProjectFolderNode
+Name=management
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes]
+Count=2
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0]
+ClassName=TProjectFolderNode
+Name=commands
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes]
+Count=3
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\management\commands\__init__.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\management\commands\mark_offensive_cron.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\management\commands\sample_command.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\management\__init__.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1]
+ClassName=TProjectFolderNode
+Name=templatetags
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1\ChildNodes]
+Count=3
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node0]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\templatetags\__init__.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\templatetags\extra_filters.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\templatetags\extra_tags.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\__init__.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node3]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\admin.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node4]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\auth.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node5]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\const.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node6]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\diff.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node7]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\forms.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node8]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\managers.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node9]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\models.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node10]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\user.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node11]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\forum\views.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2]
+ClassName=TProjectFolderNode
+Name=sql_scripts
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes]
+Count=6
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node0]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\sql_scripts\cnprog_new_install.sql
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_01_13_001.sql
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_01_13_002.sql
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node3]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_12_24_001.sql
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node4]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_12_27_001.sql
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node5]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_12_27_002.sql
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3]
+ClassName=TProjectFolderNode
+Name=templates
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes]
+Count=44
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0]
+ClassName=TProjectFolderNode
+Name=authopenid
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes]
+Count=10
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node0]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\changeemail.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\changeopenid.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\changepw.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node3]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\complete.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node4]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\delete.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node5]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\failure.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node6]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\sendpw.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node7]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\settings.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node8]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\signin.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node9]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\authopenid\signup.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1]
+ClassName=TProjectFolderNode
+Name=content
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes]
+Count=2
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0]
+ClassName=TProjectFolderNode
+Name=js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes]
+Count=10
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0]
+ClassName=TProjectFolderNode
+Name=wmd
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes]
+Count=3
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\wmd\showdown.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\wmd\wmd-base.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\wmd\wmd-plus.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\com.cnprog.editor.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\com.cnprog.post.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node3]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\com.cnprog.utils.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node4]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\excanvas.pack.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node5]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\jquery.flot.pack.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node6]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\jquery.openid.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node7]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\jquery.validate.pack.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node8]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\jquery-1.2.6.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node9]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\js\jquery-1.2.6.min.js
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1]
+ClassName=TProjectFolderNode
+Name=style
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes]
+Count=4
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node0]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\style\default.css
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\style\jquery.autocomplete.css
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\style\openid.css
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node3]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\content\style\prettify.css
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\404.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node3]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\500.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node4]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\about.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node5]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\answer_edit.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node6]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\ask.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node7]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\badge.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node8]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\badges.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node9]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\base.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node10]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\base_content.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node11]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\close.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node12]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\faq.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node13]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\footer.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node14]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\header.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node15]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\index.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node16]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\logout.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node17]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\pagesize.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node18]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\paginator.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node19]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\privacy.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node20]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\question.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node21]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\question_edit.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node22]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\question_retag.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node23]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\questions.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node24]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\reopen.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node25]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\revisions_answer.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node26]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\revisions_question.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node27]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\sidebar.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node28]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\tags.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node29]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\unanswered.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node30]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node31]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_edit.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node32]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_favorites.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node33]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_footer.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node34]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_info.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node35]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_preferences.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node36]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_recent.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node37]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_reputation.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node38]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_responses.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node39]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_stats.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node40]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_tabs.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node41]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\user_votes.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node42]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\users.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node43]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\templates\users_questions.html
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4]
+ClassName=TProjectFolderNode
+Name=utils
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes]
+Count=4
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes\Node0]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\utils\__init__.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes\Node1]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\utils\cache.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes\Node2]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\utils\html.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes\Node3]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\utils\lists.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node5]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\__init__.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node6]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\manage.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node7]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\settings.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node8]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\test.py
+
+[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node9]
+ClassName=TProjectFileNode
+FileName=C:\Projects\Lanai\src\urls.py
+
+[Project\ChildNodes\Node1]
+ClassName=TProjectRunConfiguationsNode
+
+[Project\ExtraPythonPath]
+Count=0
+
diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo
deleted file mode 100644
index 8c359972..00000000
--- a/locale/en/LC_MESSAGES/django.mo
+++ /dev/null
Binary files differ
diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po
index 93cfdfe4..c4c1e674 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-07-28 15:57+0000\n"
+"POT-Creation-Date: 2009-06-22 20:40-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,11 +16,11 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: settings.py:12
+#: settings.py:32
msgid "account/"
msgstr ""
-#: settings.py:12 django_authopenid/urls.py:9 django_authopenid/urls.py:11
+#: settings.py:32 django_authopenid/urls.py:9 django_authopenid/urls.py:11
msgid "signin/"
msgstr ""
@@ -237,7 +237,7 @@ msgstr ""
msgid "question"
msgstr ""
-#: forum/const.py:57 templates/book.html:110
+#: forum/const.py:57 templates/book.html:110 templates/backup/book.html:110
msgid "answer"
msgstr ""
@@ -317,7 +317,12 @@ msgstr ""
msgid "retagged"
msgstr ""
-#: forum/feed.py:17
+#: forum/feed.py:17 templates/base.html:7 templates/base_content.html:6
+#: templates/faq.html:25 templates/faq.html.py:108
+#: templates/backup/base.html:7 templates/backup/base_content.html:6
+#: templates/backup/faq.html:25 templates/backup/faq.html.py:108
+#: templates/tough/faq.html:23 templates/tough/faq.html.py:106
+#: templates/tough/question_retag.html:89
msgid "site title"
msgstr ""
@@ -325,7 +330,8 @@ msgstr ""
msgid " - "
msgstr ""
-#: forum/feed.py:17
+#: forum/feed.py:17 templates/base.html:7 templates/base_content.html:6
+#: templates/backup/base.html:7 templates/backup/base_content.html:6
msgid "site slogan"
msgstr ""
@@ -333,16 +339,21 @@ msgstr ""
msgid "latest questions"
msgstr ""
-#: forum/feed.py:20
+#: forum/feed.py:19 templates/index.html:8 templates/backup/index.html:8
msgid "meta site content"
msgstr ""
-#: forum/feed.py:22
+#: forum/feed.py:21
msgid "copyright message"
msgstr ""
-#: forum/forms.py:14 templates/question_edit_tips.html:31
+#: forum/forms.py:14 templates/answer_edit_tips.html:34
+#: templates/answer_edit_tips.html.py:39 templates/question_edit_tips.html:31
#: templates/question_edit_tips.html:36
+#: templates/backup/answer_edit_tips.html:33
+#: templates/backup/answer_edit_tips.html:38
+#: templates/backup/question_edit_tips.html:29
+#: templates/backup/question_edit_tips.html:34
msgid "title"
msgstr ""
@@ -363,6 +374,7 @@ msgid "question content must be > 10 characters"
msgstr ""
#: forum/forms.py:45 templates/header.html:30 templates/header.html.py:61
+#: templates/backup/header.html:30 templates/backup/header.html.py:59
msgid "tags"
msgstr ""
@@ -389,8 +401,13 @@ msgid ""
msgstr ""
#: forum/forms.py:74 templates/index.html:56 templates/question.html:196
-#: templates/question.html.py:377 templates/unanswered.html:48
-#: templates/unanswered.html.py:60
+#: templates/question.html.py:377 templates/questions.html:58
+#: templates/questions.html.py:70 templates/unanswered.html:48
+#: templates/unanswered.html.py:60 templates/backup/index.html:56
+#: templates/backup/question.html:195 templates/backup/question.html.py:367
+#: templates/backup/questions.html:57 templates/backup/questions.html.py:69
+#: templates/backup/unanswered.html:47 templates/backup/unanswered.html:59
+#: templates/tough/unanswered.html:46 templates/tough/unanswered.html.py:58
msgid "community wiki"
msgstr ""
@@ -442,123 +459,134 @@ msgstr ""
msgid "this email has already been registered, please use another one"
msgstr ""
-#: forum/models.py:316 templates/badges.html:50
+#: forum/models.py:316 templates/badges.html:52
+#: templates/backup/badges.html:52
msgid "gold"
msgstr ""
-#: forum/models.py:317 templates/badges.html:58
+#: forum/models.py:317 templates/badges.html:62
+#: templates/backup/badges.html:62
msgid "silver"
msgstr ""
-#: forum/models.py:318 templates/badges.html:65
+#: forum/models.py:318 templates/badges.html:70
+#: templates/backup/badges.html:70
msgid "bronze"
msgstr ""
-#: forum/user.py:17 templates/user_tabs.html:7
+#: forum/user.py:16 templates/user_tabs.html:7
+#: templates/backup/user_tabs.html:6
msgid "overview"
msgstr ""
-#: forum/user.py:18
+#: forum/user.py:17
msgid "user profile"
msgstr ""
-#: forum/user.py:19
+#: forum/user.py:18
msgid "user profile overview"
msgstr ""
-#: forum/user.py:25 templates/user_tabs.html:9
+#: forum/user.py:24 templates/user_tabs.html:9
+#: templates/backup/user_tabs.html:8
msgid "recent activity"
msgstr ""
-#: forum/user.py:26
+#: forum/user.py:25
msgid "recent user activity"
msgstr ""
-#: forum/user.py:27
+#: forum/user.py:26
msgid "profile - recent activity"
msgstr ""
-#: forum/user.py:34 templates/user_tabs.html:13
+#: forum/user.py:33 templates/user_tabs.html:13
+#: templates/backup/user_tabs.html:12
msgid "responses"
msgstr ""
-#: forum/user.py:35 templates/user_tabs.html:12
+#: forum/user.py:34 templates/user_tabs.html:12
+#: templates/backup/user_tabs.html:11
msgid "comments and answers to others questions"
msgstr ""
-#: forum/user.py:36
+#: forum/user.py:35
msgid "profile - responses"
msgstr ""
-#: forum/user.py:43 templates/user_info.html:23 templates/users.html:25
+#: forum/user.py:42 templates/user_info.html:23 templates/users.html:26
+#: templates/backup/user_info.html:22 templates/backup/users.html:25
msgid "reputation"
msgstr ""
-#: forum/user.py:44
+#: forum/user.py:43
msgid "user reputation in the community"
msgstr ""
-#: forum/user.py:45
+#: forum/user.py:44
msgid "profile - user reputation"
msgstr ""
-#: forum/user.py:51
+#: forum/user.py:50
msgid "favorite questions"
msgstr ""
-#: forum/user.py:52
+#: forum/user.py:51
msgid "users favorite questions"
msgstr ""
-#: forum/user.py:53
+#: forum/user.py:52
msgid "profile - favorite questions"
msgstr ""
-#: forum/user.py:60 templates/user_tabs.html:20
+#: forum/user.py:59 templates/user_tabs.html:20
+#: templates/backup/user_tabs.html:19
msgid "casted votes"
-msgstr ""
+msgstr "votes"
-#: forum/user.py:61 templates/user_tabs.html:20
+#: forum/user.py:60 templates/user_tabs.html:20
+#: templates/backup/user_tabs.html:19
msgid "user vote record"
msgstr ""
-#: forum/user.py:62
+#: forum/user.py:61
msgid "profile - votes"
msgstr ""
-#: forum/user.py:69
+#: forum/user.py:68
msgid "preferences"
msgstr ""
-#: forum/user.py:70 templates/user_tabs.html:28
+#: forum/user.py:69 templates/user_tabs.html:28
+#: templates/backup/user_tabs.html:27
msgid "user preference settings"
msgstr ""
-#: forum/user.py:71
+#: forum/user.py:70
msgid "profile - user preferences"
msgstr ""
-#: forum/views.py:1726
+#: forum/views.py:1730
msgid "uploading images is limited to users with >60 reputation points"
msgstr ""
-#: forum/views.py:1728
+#: forum/views.py:1732
msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"
msgstr ""
-#: forum/views.py:1730
+#: forum/views.py:1734
#, python-format
msgid "maximum upload file size is %sK"
msgstr ""
-#: forum/views.py:1732
+#: forum/views.py:1736
#, python-format
msgid ""
"Error uploading file. Please contact the site administrator. Thank you. %s"
msgstr ""
#: forum/templatetags/extra_tags.py:139 forum/templatetags/extra_tags.py:168
-#: templates/header.html:33
+#: templates/header.html:33 templates/backup/header.html:33
msgid "badges"
msgstr ""
@@ -570,669 +598,1135 @@ msgstr ""
msgid " ago"
msgstr ""
-#: templates/404.html:24
+#: templates/404.html:24 templates/backup/404.html:24
msgid "Sorry, could not find the page you requested."
msgstr ""
-#: templates/404.html:26
+#: templates/404.html:26 templates/backup/404.html:26
msgid "This might have happened for the following reasons:"
msgstr ""
-#: templates/404.html:28
+#: templates/404.html:28 templates/backup/404.html:28
msgid "this question or answer has been deleted;"
msgstr ""
-#: templates/404.html:29
+#: templates/404.html:29 templates/backup/404.html:29
msgid "url has error - please check it;"
msgstr ""
-#: templates/404.html:30
+#: templates/404.html:30 templates/backup/404.html:30
msgid ""
"the page you tried to visit is protected or you don't have sufficient "
"points, see"
msgstr ""
-#: templates/404.html:31
+#: templates/404.html:31 templates/backup/404.html:31
msgid "if you believe this error 404 should not have occured, please"
msgstr ""
-#: templates/404.html:32
+#: templates/404.html:32 templates/backup/404.html:32
msgid "report this problem"
msgstr ""
-#: templates/404.html:41 templates/500.html:27
+#: templates/404.html:41 templates/500.html:27 templates/backup/404.html:41
+#: templates/backup/500.html:27
msgid "back to previous page"
msgstr ""
-#: templates/404.html:42
+#: templates/404.html:42 templates/backup/404.html:42
msgid "see all questions"
msgstr ""
-#: templates/404.html:43
+#: templates/404.html:43 templates/backup/404.html:43
msgid "see all tags"
msgstr ""
-#: templates/500.html:24
+#: templates/500.html:24 templates/backup/500.html:24
msgid "system error log is recorded, error will be fixed as soon as possible"
msgstr ""
-#: templates/500.html:25
+#: templates/500.html:25 templates/backup/500.html:25
msgid "please report the error to the site administrators if you wish"
msgstr ""
-#: templates/500.html:28
+#: templates/500.html:28 templates/backup/500.html:28
msgid "see latest questions"
msgstr ""
-#: templates/500.html:29
+#: templates/500.html:29 templates/backup/500.html:29
msgid "see tags"
msgstr ""
+#: templates/about.html:6 templates/about.html.py:11
+#: templates/backup/about.html:6 templates/backup/about.html.py:11
+msgid "About"
+msgstr ""
+
#: templates/answer_edit.html:4 templates/answer_edit.html.py:47
+#: templates/backup/answer_edit.html:3 templates/backup/answer_edit.html:46
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:37
#: templates/question.html.py:40 templates/question_edit.html:27
+#: templates/backup/answer_edit.html:23 templates/backup/answer_edit.html:26
+#: templates/backup/ask.html:24 templates/backup/ask.html.py:27
+#: templates/backup/question.html:36 templates/backup/question.html.py:39
+#: templates/backup/question_edit.html:25
msgid "hide preview"
msgstr ""
#: templates/answer_edit.html:27 templates/ask.html:28
#: templates/question.html:40 templates/question_edit.html:27
+#: templates/backup/answer_edit.html:26 templates/backup/ask.html:27
+#: templates/backup/question.html:39 templates/backup/question_edit.html:25
msgid "show preview"
msgstr ""
#: templates/answer_edit.html:47 templates/question_edit.html:65
#: templates/revisions_answer.html:36 templates/revisions_question.html:36
+#: templates/backup/answer_edit.html:46 templates/backup/question_edit.html:63
+#: templates/backup/revisions_answer.html:35
+#: templates/backup/revisions_question.html:34
+#: templates/tough/question_retag.html:51
msgid "back"
msgstr ""
#: templates/answer_edit.html:52 templates/question_edit.html:70
#: templates/revisions_answer.html:47 templates/revisions_question.html:47
+#: templates/backup/answer_edit.html:51 templates/backup/question_edit.html:68
+#: templates/backup/revisions_answer.html:46
+#: templates/backup/revisions_question.html:45
msgid "revision"
msgstr ""
#: templates/answer_edit.html:55 templates/question_edit.html:74
+#: templates/backup/answer_edit.html:54 templates/backup/question_edit.html:72
msgid "select revision"
msgstr ""
#: templates/answer_edit.html:62 templates/ask.html:81
#: templates/question.html:447 templates/question_edit.html:91
+#: templates/backup/answer_edit.html:61 templates/backup/ask.html:80
+#: templates/backup/question.html:437 templates/backup/question_edit.html:89
msgid "Toggle the real time Markdown editor preview"
msgstr ""
#: templates/answer_edit.html:62 templates/ask.html:81
#: templates/question.html:447 templates/question_edit.html:91
+#: templates/backup/answer_edit.html:61 templates/backup/ask.html:80
+#: templates/backup/question.html:437 templates/backup/question_edit.html:89
msgid "toggle preview"
msgstr ""
#: templates/answer_edit.html:73 templates/question_edit.html:119
+#: templates/backup/answer_edit.html:72
+#: templates/backup/question_edit.html:117
msgid "Save edit"
msgstr ""
#: templates/answer_edit.html:74 templates/close.html:29
#: templates/question_edit.html:120 templates/reopen.html:30
-#: templates/user_edit.html:83
+#: templates/user_edit.html:83 templates/backup/answer_edit.html:73
+#: templates/backup/close.html:29 templates/backup/question_edit.html:118
+#: templates/backup/reopen.html:28 templates/backup/user_edit.html:81
+#: templates/tough/question_retag.html:75
msgid "Cancel"
msgstr ""
-#: templates/ask.html:4 templates/ask.html.py:60
+#: templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr "Tips"
+
+#: templates/answer_edit_tips.html:7 templates/backup/answer_edit_tips.html:6
+msgid "please make your answer relevant to this community"
+msgstr ""
+
+#: templates/answer_edit_tips.html:10 templates/backup/answer_edit_tips.html:9
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr ""
+
+#: templates/answer_edit_tips.html:13
+#: templates/backup/answer_edit_tips.html:12
+msgid "please try to provide details"
+msgstr ""
+
+#: templates/answer_edit_tips.html:16 templates/question_edit_tips.html:13
+#: templates/backup/answer_edit_tips.html:15
+#: templates/backup/question_edit_tips.html:11
+msgid "be clear and concise"
+msgstr ""
+
+#: templates/answer_edit_tips.html:19 templates/question_edit_tips.html:16
+#: templates/backup/answer_edit_tips.html:18
+#: templates/backup/question_edit_tips.html:14
+msgid "see frequently asked questions"
+msgstr ""
+
+#: templates/answer_edit_tips.html:25 templates/question_edit_tips.html:22
+#: templates/backup/answer_edit_tips.html:24
+#: templates/backup/question_edit_tips.html:20
+msgid "Markdown tips"
+msgstr "Markdown basics"
+
+#: templates/answer_edit_tips.html:28 templates/question_edit_tips.html:25
+#: templates/backup/answer_edit_tips.html:27
+#: templates/backup/question_edit_tips.html:23
+msgid "*italic* or __italic__"
+msgstr ""
+
+#: templates/answer_edit_tips.html:31 templates/question_edit_tips.html:28
+#: templates/backup/answer_edit_tips.html:30
+#: templates/backup/question_edit_tips.html:26
+msgid "**bold** or __bold__"
+msgstr ""
+
+#: templates/answer_edit_tips.html:34 templates/question_edit_tips.html:31
+#: templates/backup/answer_edit_tips.html:33
+#: templates/backup/question_edit_tips.html:29
+msgid "link"
+msgstr ""
+
+#: templates/answer_edit_tips.html:34 templates/answer_edit_tips.html.py:39
+#: templates/question_edit_tips.html:31 templates/question_edit_tips.html:36
+#: templates/backup/answer_edit_tips.html:33
+#: templates/backup/answer_edit_tips.html:38
+#: templates/backup/question_edit_tips.html:29
+#: templates/backup/question_edit_tips.html:34
+msgid "text"
+msgstr ""
+
+#: templates/answer_edit_tips.html:39 templates/question_edit_tips.html:36
+#: templates/backup/answer_edit_tips.html:38
+#: templates/backup/question_edit_tips.html:34
+msgid "image"
+msgstr ""
+
+#: templates/answer_edit_tips.html:43 templates/question_edit_tips.html:40
+#: templates/backup/answer_edit_tips.html:42
+#: templates/backup/question_edit_tips.html:38
+msgid "numbered list:"
+msgstr ""
+
+#: templates/answer_edit_tips.html:48 templates/question_edit_tips.html:45
+#: templates/backup/answer_edit_tips.html:47
+#: templates/backup/question_edit_tips.html:43
+msgid "basic HTML tags are also supported"
+msgstr ""
+
+#: templates/answer_edit_tips.html:51 templates/question_edit_tips.html:48
+#: templates/backup/answer_edit_tips.html:50
+#: templates/backup/question_edit_tips.html:46
+msgid "learn more about Markdown"
+msgstr ""
+
+#: templates/ask.html:4 templates/ask.html.py:60 templates/backup/ask.html:3
+#: templates/backup/ask.html.py:59
msgid "Ask a question"
msgstr ""
-#: templates/ask.html:106
+#: templates/ask.html:106 templates/backup/ask.html:105
msgid "Use"
msgstr ""
-#: templates/ask.html:106
+#: templates/ask.html:106 templates/backup/ask.html:105
msgid "learn more about OpenID"
msgstr ""
-#: templates/ask.html:106 templates/authopenid/signin.html:35
-#: templates/authopenid/signin.html:61
+#: templates/ask.html:106 templates/authopenid/signin.html:34
+#: templates/authopenid/signin.html:60 templates/backup/ask.html:105
msgid "Login"
msgstr ""
-#: templates/ask.html:109
+#: templates/ask.html:109 templates/backup/ask.html:108
msgid "Get your own "
msgstr ""
#: templates/ask.html:117 templates/authopenid/sendpw.html:27
+#: templates/backup/ask.html:116
msgid "User name"
msgstr ""
-#: templates/ask.html:120
+#: templates/ask.html:120 templates/backup/ask.html:119
msgid "Email: (won't be shown to anyone)"
msgstr ""
-#: templates/ask.html:127
+#: templates/ask.html:127 templates/backup/ask.html:126
msgid "Ask your question"
msgstr ""
#: templates/badge.html:6 templates/badge.html.py:17
+#: templates/backup/badge.html:5 templates/backup/badge.html.py:16
msgid "Badge"
msgstr ""
-#: templates/badge.html:26
+#: templates/badge.html:26 templates/backup/badge.html:25
msgid "The users have been awarded with badges:"
msgstr ""
-#: templates/badges.html:5
+#: templates/badges.html:6 templates/backup/badges.html:6
msgid "Badges summary"
msgstr ""
-#: templates/badges.html:16 templates/user_stats.html:113
+#: templates/badges.html:17 templates/user_stats.html:113
+#: templates/backup/badges.html:17 templates/backup/user_stats.html:112
msgid "Badges"
msgstr ""
-#: templates/badges.html:20
+#: templates/badges.html:21 templates/backup/badges.html:21
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr ""
+
+#: templates/badges.html:22 templates/backup/badges.html:22
msgid ""
-"Community gives you awards for your questions, answers and votes. 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 of times each type of badge "
+"has been awarded."
msgstr ""
-#: templates/badges.html:47
+#: templates/badges.html:49 templates/backup/badges.html:49
msgid "Community badges"
msgstr ""
-#: templates/badges.html:53
-msgid ""
-"Gold badge is very rare. To obtain it you have to show profound knowledge "
-"and ability in addition to actively participating in the community. Gold "
-"badge is the highest award in this community."
+#: templates/badges.html:55 templates/backup/badges.html:55
+msgid "Gold badge is very rare."
msgstr ""
-#: templates/badges.html:61
+#: templates/badges.html:56 templates/backup/badges.html:56
msgid ""
-"Obtaining silver badge requires significant patience. If you got one, you've "
-"very significantly contributed to this community"
+"To obtain it you have to show profound knowledge and ability in addition to "
+"actively participating in the community."
+msgstr ""
+
+#: templates/badges.html:57 templates/backup/badges.html:57
+msgid "Gold badge is the highest award in this community."
+msgstr ""
+
+#: templates/badges.html:65 templates/backup/badges.html:65
+msgid "Obtaining silver badge requires significant patience."
+msgstr ""
+
+#: templates/badges.html:66 templates/backup/badges.html:66
+msgid "If you got one, you've very significantly contributed to this community"
msgstr ""
-#: templates/badges.html:64
+#: templates/badges.html:69 templates/backup/badges.html:69
msgid "bronze badge: often given as a special honor"
msgstr ""
-#: templates/badges.html:68
+#: templates/badges.html:73 templates/backup/badges.html:73
msgid ""
-"If you are active in this community, you will get this medal - still it is a "
-"special honor."
+"If you are active in this community, you will will get this medal - still it "
+"is a special honor."
msgstr ""
-#: templates/base.html:61 templates/base_content.html:60
+#: templates/base.html:59 templates/base_content.html:60
+#: templates/backup/base.html:59 templates/backup/base_content.html:57
msgid "congratulations, community gave you a badge"
msgstr ""
-#: templates/base.html:63 templates/base_content.html:62
+#: templates/base.html:61 templates/base_content.html:62
+#: templates/backup/base.html:61 templates/backup/base_content.html:59
msgid "profile"
msgstr ""
-#: templates/base_content.html:61
+#: templates/base_content.html:61 templates/backup/base_content.html:58
msgid "see"
msgstr ""
-#: templates/book.html:7
+#: templates/book.html:7 templates/backup/book.html:7
msgid "reading channel"
msgstr ""
-#: templates/book.html:26
+#: templates/book.html:26 templates/backup/book.html:26
msgid "[author]"
msgstr ""
-#: templates/book.html:30
+#: templates/book.html:30 templates/backup/book.html:30
msgid "[publisher]"
msgstr ""
-#: templates/book.html:34
+#: templates/book.html:34 templates/backup/book.html:34
msgid "[publication date]"
msgstr ""
-#: templates/book.html:38
+#: templates/book.html:38 templates/backup/book.html:38
msgid "[price]"
msgstr ""
-#: templates/book.html:39
+#: templates/book.html:39 templates/backup/book.html:39
msgid "currency unit"
msgstr ""
-#: templates/book.html:42
+#: templates/book.html:42 templates/backup/book.html:42
msgid "[pages]"
msgstr ""
-#: templates/book.html:43
+#: templates/book.html:43 templates/backup/book.html:43
msgid "pages abbreviation"
msgstr ""
-#: templates/book.html:46
+#: templates/book.html:46 templates/backup/book.html:46
msgid "[tags]"
msgstr ""
-#: templates/book.html:56
+#: templates/book.html:56 templates/backup/book.html:56
msgid "author blog"
msgstr ""
-#: templates/book.html:62
+#: templates/book.html:62 templates/backup/book.html:62
msgid "book directory"
msgstr ""
-#: templates/book.html:66
+#: templates/book.html:66 templates/backup/book.html:66
msgid "buy online"
msgstr ""
-#: templates/book.html:79
+#: templates/book.html:79 templates/backup/book.html:79
msgid "reader questions"
msgstr ""
-#: templates/book.html:82
+#: templates/book.html:82 templates/backup/book.html:82
msgid "ask the author"
msgstr ""
#: templates/book.html:88 templates/book.html.py:93
-#: templates/users_questions.html:17
+#: templates/users_questions.html:17 templates/backup/book.html:88
+#: templates/backup/book.html.py:93 templates/backup/users_questions.html:16
msgid "this question was selected as favorite"
msgstr ""
#: templates/book.html:88 templates/book.html.py:93
#: templates/users_questions.html:11 templates/users_questions.html.py:17
+#: templates/backup/book.html:88 templates/backup/book.html.py:93
+#: templates/backup/users_questions.html:10
+#: templates/backup/users_questions.html:16
msgid "number of times"
msgstr ""
-#: templates/book.html:105 templates/index.html:47
+#: templates/book.html:105 templates/index.html:47 templates/questions.html:46
#: templates/unanswered.html:37 templates/users_questions.html:30
+#: templates/backup/book.html:105 templates/backup/index.html:47
+#: templates/backup/questions.html:45 templates/backup/unanswered.html:36
+#: templates/backup/users_questions.html:29 templates/tough/unanswered.html:35
msgid "votes"
msgstr ""
-#: templates/book.html:108
+#: templates/book.html:108 templates/backup/book.html:108
msgid "the answer has been accepted to be correct"
msgstr ""
-#: templates/book.html:115 templates/index.html:48
+#: templates/book.html:115 templates/index.html:48 templates/questions.html:47
#: templates/unanswered.html:38 templates/users_questions.html:40
+#: templates/backup/book.html:115 templates/backup/index.html:48
+#: templates/backup/questions.html:46 templates/backup/unanswered.html:37
+#: templates/backup/users_questions.html:39 templates/tough/unanswered.html:36
msgid "views"
msgstr ""
#: templates/book.html:125 templates/index.html:68 templates/question.html:112
-#: templates/question.html.py:479 templates/tags.html:46
+#: templates/question.html.py:479 templates/questions.html:84
+#: templates/questions.html.py:149 templates/tags.html:47
#: templates/unanswered.html:75 templates/unanswered.html.py:109
-#: templates/users_questions.html:52
+#: templates/users_questions.html:52 templates/backup/book.html:125
+#: templates/backup/index.html:68 templates/backup/index.html.py:93
+#: templates/backup/question.html:111 templates/backup/question.html.py:469
+#: templates/backup/questions.html:83 templates/backup/questions.html:148
+#: templates/backup/tags.html:46 templates/backup/unanswered.html:74
+#: templates/backup/unanswered.html:108
+#: templates/backup/users_questions.html:51 templates/tough/unanswered.html:72
+#: templates/tough/unanswered.html:105
msgid "using tags"
msgstr ""
-#: templates/book.html:147
+#: templates/book.html:147 templates/backup/book.html:147
msgid "subscribe to book RSS feed"
msgstr ""
-#: templates/book.html:147 templates/index.html:115
+#: templates/book.html:147 templates/index.html:116
+#: templates/backup/book.html:147 templates/backup/index.html:115
msgid "subscribe to the questions feed"
msgstr ""
#: templates/close.html:6 templates/close.html.py:16
+#: templates/backup/close.html:6 templates/backup/close.html.py:16
msgid "Close question"
msgstr ""
-#: templates/close.html:19
+#: templates/close.html:19 templates/backup/close.html:19
msgid "Close the question"
msgstr ""
-#: templates/close.html:25
+#: templates/close.html:25 templates/backup/close.html:25
msgid "Reasons"
msgstr ""
-#: templates/close.html:28
+#: templates/close.html:28 templates/backup/close.html:28
msgid "OK to close"
msgstr ""
-#: templates/footer.html:5
-msgid "About us"
+#: templates/faq.html:11 templates/backup/faq.html:11
+#: templates/tough/faq.html:9
+msgid "Frequently Asked Questions "
msgstr ""
-#: templates/footer.html:6 templates/header.html:13 templates/index.html:83
-msgid "faq"
+#: templates/faq.html:15 templates/backup/faq.html:15
+#: templates/tough/faq.html:13
+msgid "What kinds of questions can I ask here?"
msgstr ""
-#: templates/footer.html:8
-msgid "Contact"
+#: templates/faq.html:16 templates/backup/faq.html:16
+#: templates/tough/faq.html:14
+msgid ""
+"Most importanly - questions should be <strong>relevant</strong> to this "
+"community."
msgstr ""
-#: templates/footer.html:9
-msgid "Privacy"
+#: templates/faq.html:17 templates/backup/faq.html:17
+#: templates/tough/faq.html:15
+msgid ""
+"Before asking the question - please make sure to use search to see whether "
+"your question has alredy been answered."
msgstr ""
-#: templates/footer.html:10
-msgid "Feedback"
+#: templates/faq.html:20 templates/backup/faq.html:20
+#: templates/tough/faq.html:18
+msgid "What questions should I avoid asking?"
msgstr ""
-#: templates/header.html:8
-msgid "logout"
+#: templates/faq.html:21 templates/backup/faq.html:21
+#: templates/tough/faq.html:19
+msgid ""
+"Please avoid asking questions that are not relevant to this community, too "
+"subjective and argumentative."
msgstr ""
-#: templates/header.html:10 templates/authopenid/signup.html:39
-msgid "login"
+#: templates/faq.html:24 templates/backup/faq.html:24
+#: templates/tough/faq.html:22
+msgid "What should I avoid in my answers?"
msgstr ""
-#: templates/header.html:12 templates/index.html:82
-msgid "about"
+#: templates/faq.html:25 templates/backup/faq.html:25
+#: templates/tough/faq.html:23
+msgid ""
+"is a Q&A site, not a discussion group. Therefore - please avoid having "
+"discussions in your answers, comment facility allows some space for brief "
+"discussions."
msgstr ""
-#: templates/header.html:23
-msgid "back to home page"
+#: templates/faq.html:28 templates/backup/faq.html:28
+#: templates/tough/faq.html:26
+msgid "Who moderates this community?"
+msgstr ""
+
+#: templates/faq.html:29 templates/backup/faq.html:29
+#: templates/tough/faq.html:27
+msgid "The short answer is: <strong>you</strong>."
+msgstr ""
+
+#: templates/faq.html:30 templates/backup/faq.html:30
+#: templates/tough/faq.html:28
+msgid "This website is moderated by the users."
+msgstr ""
+
+#: templates/faq.html:31 templates/backup/faq.html:31
+#: templates/tough/faq.html:29
+msgid ""
+"The reputation system allows users earn the authorization to perform a "
+"variety of moderation tasks."
+msgstr ""
+
+#: templates/faq.html:34 templates/backup/faq.html:34
+#: templates/tough/faq.html:32
+msgid "How does reputation system work?"
+msgstr ""
+
+#: templates/faq.html:35 templates/backup/faq.html:35
+#: templates/tough/faq.html:33
+msgid ""
+"Anyone can ask questions and give answers, points are not necessary for that."
+msgstr ""
+
+#: templates/faq.html:36 templates/backup/faq.html:36
+#: templates/tough/faq.html:34
+msgid ""
+"As we've said before, users help running this site. Point system helps "
+"select users who can administer this community."
+msgstr ""
+
+#: templates/faq.html:37 templates/backup/faq.html:37
+#: templates/tough/faq.html:35
+msgid ""
+"Reputation points roughly measure how community trusts you. These points are "
+"given to you directly by other members of the community."
+msgstr ""
+
+#: templates/faq.html:40 templates/backup/faq.html:40
+#: templates/tough/faq.html:38
+msgid ""
+"For example, if you ask an interesting question or give a helpful answer, "
+"your input will be upvoted and you will gain more trust in the community."
+msgstr ""
+
+#: templates/faq.html:41 templates/backup/faq.html:41
+#: templates/tough/faq.html:39
+msgid ""
+"If on the other hand someone gives a misleading answer, the answer will be "
+"voted down and he/she loses some points."
+msgstr ""
+
+#: templates/faq.html:42 templates/backup/faq.html:42
+#: templates/tough/faq.html:40
+msgid ""
+"Each vote in favor will generate <strong>10</strong> points, each vote "
+"against will subtract <strong>2</strong> points."
+msgstr ""
+
+#: templates/faq.html:43 templates/backup/faq.html:43
+#: templates/tough/faq.html:41
+msgid ""
+"Through the votes of other people you can accumulate a maximum of "
+"<strong>200</strong> points."
+msgstr ""
+
+#: templates/faq.html:44 templates/backup/faq.html:44
+msgid "After accumulating certain number of points, you can do more:"
+msgstr ""
+
+#: templates/faq.html:52 templates/user_votes.html:14
+#: templates/backup/faq.html:52 templates/backup/user_votes.html:13
+#: templates/tough/faq.html:50
+msgid "upvote"
+msgstr ""
+
+#: templates/faq.html:56 templates/backup/faq.html:56
+#: templates/tough/faq.html:54
+msgid "use tags"
+msgstr ""
+
+#: templates/faq.html:60 templates/backup/faq.html:60
+#: templates/tough/faq.html:58
+msgid "add comments"
msgstr ""
-#: templates/header.html:29 templates/header.html.py:60
+#: templates/faq.html:64 templates/user_votes.html:16
+#: templates/backup/faq.html:64 templates/backup/user_votes.html:15
+#: templates/tough/faq.html:62
+msgid "downvote"
+msgstr ""
+
+#: templates/faq.html:71 templates/backup/faq.html:71
+#: templates/tough/faq.html:69
+msgid "retag questions"
+msgstr ""
+
+#: templates/faq.html:75 templates/backup/faq.html:75
+#: templates/tough/faq.html:73
+msgid "edit community wiki questions"
+msgstr ""
+
+#: templates/faq.html:79 templates/backup/faq.html:79
+#: templates/tough/faq.html:77
+msgid "edit any answer"
+msgstr ""
+
+#: templates/faq.html:83 templates/backup/faq.html:83
+#: templates/tough/faq.html:81
+msgid "open any closed question"
+msgstr ""
+
+#: templates/faq.html:87 templates/backup/faq.html:87
+#: templates/tough/faq.html:85
+msgid "delete any comment"
+msgstr ""
+
+#: templates/faq.html:91 templates/backup/faq.html:91
+#: templates/tough/faq.html:89
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr ""
+
+#: templates/faq.html:98 templates/backup/faq.html:98
+msgid "To register, do I need to create new password?"
+msgstr ""
+
+#: templates/faq.html:99 templates/backup/faq.html:99
+#: templates/tough/faq.html:97
+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:100 templates/backup/faq.html:100
+#: templates/tough/faq.html:98
+msgid "Login now!"
+msgstr ""
+
+#: templates/faq.html:103 templates/backup/faq.html:103
+#: templates/tough/faq.html:101
+msgid "Why other people can edit my questions/answers?"
+msgstr ""
+
+#: templates/faq.html:104 templates/backup/faq.html:104
+#: templates/tough/faq.html:102
+msgid "Goal of this site is..."
+msgstr ""
+
+#: templates/faq.html:104 templates/backup/faq.html:104
+#: templates/tough/faq.html:102
+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:105 templates/backup/faq.html:105
+#: templates/tough/faq.html:103
+msgid "If this approach is not for you, we respect your choice."
+msgstr ""
+
+#: templates/faq.html:107 templates/backup/faq.html:107
+#: templates/tough/faq.html:105
+msgid "Still have questions?"
+msgstr ""
+
+#: templates/faq.html:108 templates/backup/faq.html:108
+msgid "Please ask your question, help make our community better!"
+msgstr ""
+
+#: templates/faq.html:108 templates/header.html:29 templates/header.html.py:60
+#: templates/backup/faq.html:108 templates/backup/header.html:29
+#: templates/backup/header.html.py:58 templates/tough/faq.html:106
msgid "questions"
msgstr ""
+#: templates/faq.html:108 templates/index.html:121
+#: templates/backup/faq.html:108 templates/backup/index.html:120
+#: templates/tough/faq.html:106
+msgid "."
+msgstr ""
+
+#: templates/footer.html:7 templates/header.html:12 templates/index.html:83
+#: templates/backup/footer.html:7 templates/backup/header.html:12
+#: templates/backup/index.html:83
+msgid "about"
+msgstr ""
+
+#: templates/footer.html:8 templates/header.html:13 templates/index.html:84
+#: templates/backup/footer.html:8 templates/backup/header.html:13
+#: templates/backup/index.html:84
+msgid "faq"
+msgstr ""
+
+#: templates/footer.html:9 templates/backup/footer.html:9
+msgid "blog"
+msgstr ""
+
+#: templates/footer.html:10 templates/backup/footer.html:10
+msgid "contact us"
+msgstr ""
+
+#: templates/footer.html:11 templates/backup/footer.html:11
+msgid "privacy policy"
+msgstr ""
+
+#: templates/footer.html:12 templates/backup/footer.html:12
+msgid "give feedback"
+msgstr ""
+
+#: templates/footer.html:18 templates/backup/footer.html:18
+msgid "current revision"
+msgstr ""
+
+#: templates/header.html:8 templates/backup/header.html:8
+msgid "logout"
+msgstr ""
+
+#: templates/header.html:10 templates/authopenid/signup.html:39
+#: templates/backup/header.html:10
+msgid "login"
+msgstr ""
+
+#: templates/header.html:23 templates/backup/header.html:23
+msgid "back to home page"
+msgstr ""
+
#: templates/header.html:31 templates/header.html.py:62
+#: templates/backup/header.html:31 templates/backup/header.html.py:60
msgid "users"
msgstr ""
-#: templates/header.html:32
+#: templates/header.html:32 templates/backup/header.html:32
msgid "books"
msgstr ""
-#: templates/header.html:34 templates/index.html:120
+#: templates/header.html:34 templates/index.html:121
+#: templates/backup/header.html:34 templates/backup/index.html:120
msgid "unanswered questions"
-msgstr ""
+msgstr "unanswered"
-#: templates/header.html:38
+#: templates/header.html:38 templates/backup/header.html:37
msgid "my profile"
msgstr ""
-#: templates/header.html:42
+#: templates/header.html:42 templates/backup/header.html:40
msgid "ask a question"
msgstr ""
-#: templates/header.html:57
+#: templates/header.html:57 templates/backup/header.html:55
msgid "search"
msgstr ""
-#: templates/index.html:6
+#: templates/index.html:6 templates/backup/index.html:6
msgid "Home"
msgstr ""
-#: templates/index.html:21
+#: templates/index.html:7 templates/backup/index.html:7
+msgid "meta site keywords, comma separated"
+msgstr ""
+
+#: templates/index.html:21 templates/questions.html:7
+#: templates/backup/index.html:21 templates/backup/questions.html:6
msgid "Questions"
msgstr ""
-#: templates/index.html:23
+#: templates/index.html:23 templates/backup/index.html:23
msgid "last updated questions"
msgstr ""
-#: templates/index.html:23 templates/unanswered.html:20
+#: templates/index.html:23 templates/questions.html:25
+#: templates/unanswered.html:20 templates/backup/index.html:23
+#: templates/backup/questions.html:24 templates/backup/unanswered.html:19
+#: templates/tough/unanswered.html:18
msgid "newest"
msgstr ""
-#: templates/index.html:24
+#: templates/index.html:24 templates/questions.html:27
+#: templates/backup/index.html:24 templates/backup/questions.html:26
msgid "hottest questions"
msgstr ""
-#: templates/index.html:24
+#: templates/index.html:24 templates/questions.html:27
+#: templates/backup/index.html:24 templates/backup/questions.html:26
msgid "hottest"
msgstr ""
-#: templates/index.html:25
+#: templates/index.html:25 templates/questions.html:28
+#: templates/backup/index.html:25 templates/backup/questions.html:27
msgid "most voted questions"
msgstr ""
-#: templates/index.html:25
+#: templates/index.html:25 templates/questions.html:28
+#: templates/backup/index.html:25 templates/backup/questions.html:27
msgid "most voted"
msgstr ""
-#: templates/index.html:26
+#: templates/index.html:26 templates/backup/index.html:26
msgid "all questions"
msgstr ""
-#: templates/index.html:46 templates/unanswered.html:36
-#: templates/users_questions.html:35
+#: templates/index.html:46 templates/questions.html:45
+#: templates/unanswered.html:36 templates/users_questions.html:35
+#: templates/backup/index.html:46 templates/backup/questions.html:44
+#: templates/backup/unanswered.html:35
+#: templates/backup/users_questions.html:34 templates/tough/unanswered.html:34
msgid "answers"
msgstr ""
#: templates/index.html:68 templates/question.html:112
-#: templates/question.html.py:479 templates/tags.html:46
+#: templates/question.html.py:479 templates/questions.html:84
+#: templates/questions.html.py:149 templates/tags.html:47
#: templates/unanswered.html:75 templates/unanswered.html.py:109
-#: templates/users_questions.html:52
+#: templates/users_questions.html:52 templates/backup/index.html:68
+#: templates/backup/index.html.py:93 templates/backup/question.html:111
+#: templates/backup/question.html.py:469 templates/backup/questions.html:83
+#: templates/backup/questions.html:148 templates/backup/tags.html:46
+#: templates/backup/unanswered.html:74 templates/backup/unanswered.html:108
+#: templates/backup/users_questions.html:51 templates/tough/unanswered.html:72
+#: templates/tough/unanswered.html:105
msgid "see questions tagged"
msgstr ""
-#: templates/index.html:79
+#: templates/index.html:79 templates/backup/index.html:79
msgid "welcome to website"
msgstr ""
-#: templates/index.html:88
+#: templates/index.html:81 templates/backup/index.html:81
+msgid "what is this website"
+msgstr ""
+
+#: templates/index.html:82 templates/backup/index.html:82
+msgid "what can one do on this website"
+msgstr ""
+
+#: templates/index.html:89 templates/backup/index.html:89
msgid "Recent tags"
msgstr ""
-#: templates/index.html:93
+#: templates/index.html:94
#, python-format
msgid "see questions tagged '%(tagname)s'"
msgstr ""
-#: templates/index.html:96 templates/index.html.py:120
+#: templates/index.html:97 templates/index.html.py:121
+#: templates/backup/index.html:96 templates/backup/index.html.py:120
msgid "popular tags"
msgstr ""
-#: templates/index.html:100
+#: templates/index.html:101 templates/backup/index.html:100
msgid "Recent awards"
msgstr ""
-#: templates/index.html:106
+#: templates/index.html:107 templates/backup/index.html:106
msgid "given to"
msgstr ""
-#: templates/index.html:111
+#: templates/index.html:112 templates/backup/index.html:111
msgid "all awards"
msgstr ""
-#: templates/index.html:115
+#: templates/index.html:116 templates/backup/index.html:115
msgid "subscribe to last 30 questions by RSS"
msgstr ""
-#: templates/index.html:120
+#: templates/index.html:121 templates/backup/index.html:120
msgid "Still looking for more? See"
msgstr ""
-#: templates/index.html:120
+#: templates/index.html:121 templates/backup/index.html:120
msgid "complete list of quesionts"
msgstr ""
-#: templates/index.html:120
+#: templates/index.html:121 templates/backup/index.html:120
msgid "or"
msgstr ""
-#: templates/index.html:120
-msgid "."
-msgstr ""
-
-#: templates/index.html:120
+#: templates/index.html:121 templates/backup/index.html:120
msgid "Please help us answer"
msgstr ""
#: templates/logout.html:6 templates/logout.html.py:17
+#: templates/backup/logout.html:6 templates/backup/logout.html.py:17
msgid "Logout"
msgstr ""
-#: templates/logout.html:20
+#: templates/logout.html:20 templates/backup/logout.html:20
msgid ""
"As a registered user you can login with your OpenID, log out of the site or "
"permanently remove your account."
msgstr ""
-#: templates/logout.html:21
+#: templates/logout.html:21 templates/backup/logout.html:21
msgid "Logout now"
msgstr ""
-#: templates/pagesize.html:5
-msgid "Size per page:"
+#: templates/pagesize.html:6 templates/backup/pagesize.html:6
+msgid "posts per page"
msgstr ""
-#: templates/paginator.html:5
-msgid "Previous"
+#: templates/paginator.html:6 templates/paginator.html.py:7
+#: templates/backup/paginator.html:5 templates/backup/paginator.html.py:6
+msgid "previous"
+msgstr ""
+
+#: templates/paginator.html:20 templates/backup/paginator.html:19
+msgid "current page"
+msgstr ""
+
+#: templates/paginator.html:23 templates/paginator.html.py:30
+#: templates/backup/paginator.html:22 templates/backup/paginator.html.py:29
+msgid "page number "
+msgstr ""
+
+#: templates/paginator.html:23 templates/paginator.html.py:30
+#: templates/backup/paginator.html:22 templates/backup/paginator.html.py:29
+msgid "number - make blank in english"
+msgstr ""
+
+#: templates/paginator.html:34 templates/backup/paginator.html:33
+msgid "next page"
msgstr ""
#: templates/privacy.html:6 templates/privacy.html.py:11
+#: templates/backup/privacy.html:5 templates/backup/privacy.html.py:10
msgid "Privacy policy"
msgstr ""
-#: templates/privacy.html:15
+#: templates/privacy.html:15 templates/backup/privacy.html:14
msgid "general message about privacy"
msgstr ""
-#: templates/privacy.html:18
+#: templates/privacy.html:18 templates/backup/privacy.html:17
msgid "Site Visitors"
msgstr ""
-#: templates/privacy.html:20
+#: templates/privacy.html:20 templates/backup/privacy.html:19
msgid "what technical information is collected about visitors"
msgstr ""
-#: templates/privacy.html:23
+#: templates/privacy.html:23 templates/backup/privacy.html:22
msgid "Personal Information"
msgstr ""
-#: templates/privacy.html:25
+#: templates/privacy.html:25 templates/backup/privacy.html:24
msgid "details on personal information policies"
msgstr ""
-#: templates/privacy.html:28
+#: templates/privacy.html:28 templates/backup/privacy.html:27
msgid "Other Services"
msgstr ""
-#: templates/privacy.html:30
+#: templates/privacy.html:30 templates/backup/privacy.html:29
msgid "details on sharing data with third parties"
msgstr ""
-#: templates/privacy.html:35
+#: templates/privacy.html:35 templates/backup/privacy.html:34
msgid "cookie policy details"
msgstr ""
-#: templates/privacy.html:37
+#: templates/privacy.html:37 templates/backup/privacy.html:36
msgid "Policy Changes"
msgstr ""
-#: templates/privacy.html:38
+#: templates/privacy.html:38 templates/backup/privacy.html:37
msgid "how privacy policies can be changed"
msgstr ""
#: templates/question.html:66 templates/question.html.py:78
+#: templates/backup/question.html:65 templates/backup/question.html.py:77
msgid "i like this post (click again to cancel)"
msgstr ""
#: templates/question.html:68 templates/question.html.py:80
-#: templates/question.html:273
+#: templates/question.html:273 templates/backup/question.html:67
+#: templates/backup/question.html.py:79 templates/backup/question.html:272
msgid "current number of votes"
msgstr ""
#: templates/question.html:73 templates/question.html.py:84
+#: templates/backup/question.html:72 templates/backup/question.html.py:83
msgid "i dont like this post (click again to cancel)"
msgstr ""
-#: templates/question.html:90
+#: templates/question.html:90 templates/backup/question.html:89
msgid "mark this question as favorite (click again to cancel)"
msgstr ""
-#: templates/question.html:96
+#: templates/question.html:96 templates/backup/question.html:95
msgid "remove favorite mark from this question (click again to restore mark)"
msgstr ""
#: templates/question.html:121 templates/question.html.py:304
#: templates/revisions_answer.html:53 templates/revisions_question.html:53
+#: templates/backup/question.html:120 templates/backup/question.html.py:303
+#: templates/backup/revisions_answer.html:52
+#: templates/backup/revisions_question.html:51
msgid "edit"
msgstr ""
#: templates/question.html:125 templates/question.html.py:314
+#: templates/backup/question.html:124 templates/backup/question.html.py:307
msgid "delete"
msgstr ""
-#: templates/question.html:130
+#: templates/question.html:130 templates/backup/question.html:129
msgid "reopen"
msgstr ""
-#: templates/question.html:135
+#: templates/question.html:135 templates/backup/question.html:134
msgid "close"
msgstr ""
#: templates/question.html:141 templates/question.html.py:327
+#: templates/backup/question.html:140 templates/backup/question.html.py:317
msgid ""
"report as offensive (i.e containing spam, advertising, malicious text, etc.)"
msgstr ""
#: templates/question.html:142 templates/question.html.py:328
+#: templates/backup/question.html:141 templates/backup/question.html.py:318
msgid "flag offensive"
msgstr ""
#: templates/question.html:154 templates/question.html.py:337
#: templates/revisions_answer.html:65 templates/revisions_question.html:65
+#: templates/backup/question.html:153 templates/backup/question.html.py:327
+#: templates/backup/revisions_answer.html:64
+#: templates/backup/revisions_question.html:63
msgid "updated"
msgstr ""
#: templates/question.html:203 templates/question.html.py:384
#: templates/revisions_answer.html:63 templates/revisions_question.html:63
+#: templates/backup/question.html:202 templates/backup/question.html.py:374
+#: templates/backup/revisions_answer.html:62
+#: templates/backup/revisions_question.html:61
msgid "asked"
msgstr ""
#: templates/question.html:233 templates/question.html.py:411
+#: templates/backup/question.html:232 templates/backup/question.html.py:401
msgid "comments"
msgstr ""
#: templates/question.html:234 templates/question.html.py:412
+#: templates/backup/question.html:233 templates/backup/question.html.py:402
msgid "add comment"
msgstr ""
-#: templates/question.html:247
+#: templates/question.html:247 templates/backup/question.html:246
#, python-format
msgid ""
"The question has been closed for the following reason \"%(question."
"get_close_reason_display)s\" by"
msgstr ""
-#: templates/question.html:249
+#: templates/question.html:249 templates/backup/question.html:248
#, python-format
msgid "close date %(question.closed_at)s"
msgstr ""
-#: templates/question.html:256 templates/questions.html:44
-#: templates/user_stats.html:28
+#: templates/question.html:256 templates/user_stats.html:28
+#: templates/backup/question.html:255 templates/backup/user_stats.html:27
msgid "Answers"
-msgstr ""
+msgstr " Answers"
-#: templates/question.html:258
+#: templates/question.html:258 templates/backup/question.html:257
msgid "oldest answers will be shown first"
msgstr ""
-#: templates/question.html:258
+#: templates/question.html:258 templates/backup/question.html:257
msgid "oldest answers"
-msgstr ""
+msgstr "oldest"
-#: templates/question.html:259
+#: templates/question.html:259 templates/backup/question.html:258
msgid "newest answers will be shown first"
msgstr ""
-#: templates/question.html:259
+#: templates/question.html:259 templates/backup/question.html:258
msgid "newest answers"
-msgstr ""
+msgstr "newest"
-#: templates/question.html:260
+#: templates/question.html:260 templates/backup/question.html:259
msgid "most voted answers will be shown first"
msgstr ""
-#: templates/question.html:260
+#: templates/question.html:260 templates/backup/question.html:259
msgid "popular answers"
-msgstr ""
+msgstr "most voted"
-#: templates/question.html:272
+#: templates/question.html:272 templates/backup/question.html:271
msgid "i like this answer (click again to cancel)"
msgstr ""
-#: templates/question.html:278
+#: templates/question.html:278 templates/backup/question.html:277
msgid "i dont like this answer (click again to cancel)"
msgstr ""
-#: templates/question.html:284
+#: templates/question.html:284 templates/backup/question.html:283
msgid "mark this answer as favorite (click again to undo)"
msgstr ""
-#: templates/question.html:289
+#: templates/question.html:289 templates/backup/question.html:288
msgid "the author of the question has selected this answer as correct"
msgstr ""
@@ -1240,294 +1734,295 @@ msgstr ""
msgid "undelete"
msgstr ""
-#: templates/question.html:321
+#: templates/question.html:321 templates/backup/question.html:311
msgid "answer permanent link"
msgstr ""
-#: templates/question.html:322
+#: templates/question.html:322 templates/backup/question.html:312
msgid "permanent link"
msgstr ""
-#: templates/question.html:436
+#: templates/question.html:436 templates/backup/question.html:426
msgid "Your answer"
msgstr ""
-#: templates/question.html:460
+#: templates/question.html:460 templates/backup/question.html:450
msgid "Answer the question"
msgstr ""
-#: templates/question.html:462
+#: templates/question.html:462 templates/backup/question.html:452
msgid "Login to answer"
msgstr ""
-#: templates/question.html:474
+#: templates/question.html:474 templates/backup/question.html:464
msgid "Question tags"
-msgstr ""
+msgstr "Tags"
-#: templates/question.html:484
+#: templates/question.html:484 templates/backup/question.html:474
msgid "question asked"
-msgstr ""
+msgstr "Asked"
#: templates/question.html:484 templates/question.html.py:490
-#: templates/user_info.html:51
+#: templates/user_info.html:51 templates/backup/question.html:474
+#: templates/backup/question.html.py:480 templates/backup/user_info.html:50
msgid "ago"
msgstr ""
-#: templates/question.html:487
+#: templates/question.html:487 templates/backup/question.html:477
msgid "question was seen"
-msgstr ""
+msgstr "Seen"
-#: templates/question.html:487
+#: templates/question.html:487 templates/backup/question.html:477
msgid "times"
msgstr ""
-#: templates/question.html:490
+#: templates/question.html:490 templates/backup/question.html:480
msgid "last updated"
-msgstr ""
+msgstr "Last updated"
-#: templates/question.html:495
+#: templates/question.html:495 templates/backup/question.html:485
msgid "Related questions"
msgstr ""
#: templates/question_edit.html:4 templates/question_edit.html.py:65
+#: templates/backup/question_edit.html:2
+#: templates/backup/question_edit.html:63
msgid "Edit question"
msgstr ""
#: templates/question_edit_tips.html:4
msgid "question tips"
-msgstr ""
+msgstr "Tips"
#: templates/question_edit_tips.html:7
+#: templates/backup/question_edit_tips.html:5
msgid "please ask a relevant question"
msgstr ""
#: templates/question_edit_tips.html:10
+#: templates/backup/question_edit_tips.html:8
msgid "please try provide enough details"
-msgstr ""
-
-#: templates/question_edit_tips.html:13
-msgid "be clear and concise"
-msgstr ""
+msgstr "provide enough details"
-#: templates/question_edit_tips.html:16
-msgid "see frequently asked questions"
-msgstr ""
+#: templates/questions.html:23 templates/backup/questions.html:22
+msgid "Found by tags"
+msgstr "Tagged questions"
-#: templates/question_edit_tips.html:22
-msgid "Markdown tips"
-msgstr ""
-
-#: templates/question_edit_tips.html:25
-msgid "*italic* or __italic__"
-msgstr ""
-
-#: templates/question_edit_tips.html:28
-msgid "**bold** or __bold__"
-msgstr ""
-
-#: templates/question_edit_tips.html:31
-msgid "link"
-msgstr ""
-
-#: templates/question_edit_tips.html:31 templates/question_edit_tips.html:36
-msgid "text"
-msgstr ""
-
-#: templates/question_edit_tips.html:36
-msgid "image"
-msgstr ""
-
-#: templates/question_edit_tips.html:40
-msgid "numbered list:"
+#: templates/questions.html:23 templates/backup/questions.html:22
+msgid "Found by title"
msgstr ""
-#: templates/question_edit_tips.html:45
-msgid "basic HTML tags are also supported"
-msgstr ""
-
-#: templates/question_edit_tips.html:48
-msgid "learn more about Markdown"
-msgstr ""
-
-#: templates/questions.html:6
-msgid "Question list"
-msgstr ""
-
-#: templates/questions.html:22
-msgid "Tagged questions"
-msgstr ""
-
-#: templates/questions.html:22
-msgid "Query result"
-msgstr ""
-
-#: templates/questions.html:22
+#: templates/questions.html:23 templates/backup/questions.html:22
msgid "All questions"
msgstr ""
-#: templates/questions.html:24
-msgid "New questions"
+#: templates/questions.html:25 templates/unanswered.html:20
+#: templates/backup/questions.html:24 templates/backup/unanswered.html:19
+#: templates/tough/unanswered.html:18
+msgid "most recently asked questions"
msgstr ""
-#: templates/questions.html:24
-msgid "Newest"
+#: templates/questions.html:26 templates/backup/questions.html:25
+msgid "most recently updated questions"
msgstr ""
-#: templates/questions.html:25
-msgid "Newest updated questions"
+#: templates/questions.html:26 templates/backup/questions.html:25
+msgid "active"
msgstr ""
-#: templates/questions.html:25
-msgid "Active"
-msgstr ""
+#: templates/questions.html:109
+#, python-format
+msgid ""
+"\n"
+"\t\t\thave total %(q_num)s questions tagged %(tagname)s\n"
+"\t\t\t"
+msgid_plural ""
+"\n"
+"\t\t\thave total %(q_num)s questions tagged %(tagname)s\n"
+"\t\t\t"
+msgstr[0] ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>question tagged</p><p><span "
+"class=\"tag\">%(tagname)s</span></p>"
+msgstr[1] ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>questions tagged</"
+"p><p><span class=\"tag\">%(tagname)s</span></p>"
+
+#: templates/questions.html:116
+#, python-format
+msgid ""
+"\n"
+"\t\t\thave total %(q_num)s questions containing %(searchtitle)s\n"
+"\t\t\t"
+msgid_plural ""
+"\n"
+"\t\t\thave total %(q_num)s questions containing %(searchtitle)s\n"
+"\t\t\t"
+msgstr[0] ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>question with title "
+"containing <strong><span class=\"darkred\">%(searchtitle)s</span></strong></"
+"p>"
+msgstr[1] ""
+"\n"
+"<div class=\"questions-count\">%(q_num)s</div><p>questions with title "
+"containing <strong><span class=\"darkred\">%(searchtitle)s</span></strong></"
+"p>"
-#: templates/questions.html:26
-msgid "Questions with most answers"
-msgstr ""
+#: templates/questions.html:124
+msgid "latest questions info"
+msgstr "<strong>Newest</strong> questions are shown first."
-#: templates/questions.html:26
-msgid "Hottest"
+#: templates/questions.html:128 templates/backup/questions.html:127
+msgid "Questions are sorted by the <strong>time of last update</strong>."
msgstr ""
-#: templates/questions.html:27
-msgid "Questions with most votes"
+#: templates/questions.html:129 templates/backup/questions.html:128
+msgid "Most recently answered ones are shown first."
msgstr ""
-#: templates/questions.html:27
-msgid "Best"
+#: templates/questions.html:133 templates/backup/questions.html:132
+msgid "Questions sorted by <strong>number of responses</strong>."
msgstr ""
-#: templates/questions.html:45
-msgid "Votes"
+#: templates/questions.html:134 templates/backup/questions.html:133
+msgid "Most answered questions are shown first."
msgstr ""
-#: templates/questions.html:46
-msgid "Visits"
+#: templates/questions.html:138 templates/backup/questions.html:137
+msgid "Questions are sorted by the <strong>number of votes</strong>."
msgstr ""
-#: templates/questions.html:57 templates/questions.html.py:69
-msgid "Community wiki"
+#: templates/questions.html:139 templates/backup/questions.html:138
+msgid "Most voted questions are shown first."
msgstr ""
-#: templates/questions.html:83
-msgid "Browse questions with tag of "
-msgstr ""
-
-#: templates/questions.html:125 templates/unanswered.html:105
+#: templates/questions.html:146 templates/unanswered.html:105
+#: templates/backup/questions.html:145 templates/backup/unanswered.html:104
+#: templates/tough/unanswered.html:101
msgid "Related tags"
-msgstr ""
+msgstr "Tags"
#: templates/reopen.html:6 templates/reopen.html.py:16
+#: templates/backup/reopen.html:4 templates/backup/reopen.html.py:14
msgid "Reopen question"
msgstr ""
-#: templates/reopen.html:19
+#: templates/reopen.html:19 templates/backup/reopen.html:17
msgid "Open the previously closed question"
msgstr ""
-#: templates/reopen.html:22
+#: templates/reopen.html:22 templates/backup/reopen.html:20
msgid "The question was closed for the following reason "
msgstr ""
-#: templates/reopen.html:22
+#: templates/reopen.html:22 templates/backup/reopen.html:20
msgid "reason - leave blank in english"
msgstr ""
-#: templates/reopen.html:22
+#: templates/reopen.html:22 templates/backup/reopen.html:20
msgid "on "
msgstr ""
-#: templates/reopen.html:22
+#: templates/reopen.html:22 templates/backup/reopen.html:20
msgid "date closed"
msgstr ""
-#: templates/reopen.html:29
+#: templates/reopen.html:29 templates/backup/reopen.html:27
msgid "Reopen this question"
msgstr ""
#: templates/revisions_answer.html:7 templates/revisions_answer.html.py:36
#: templates/revisions_question.html:8 templates/revisions_question.html:36
+#: templates/backup/revisions_answer.html:6
+#: templates/backup/revisions_answer.html:35
+#: templates/backup/revisions_question.html:6
+#: templates/backup/revisions_question.html:34
msgid "Revision history"
msgstr ""
-#: templates/tags.html:5 templates/tags.html.py:28
+#: templates/tags.html:6 templates/tags.html.py:29
+#: templates/backup/tags.html:5 templates/backup/tags.html.py:28
msgid "Tag list"
msgstr ""
-#: templates/tags.html:30
+#: templates/tags.html:31 templates/backup/tags.html:30
msgid "sorted alphabetically"
msgstr ""
-#: templates/tags.html:30
+#: templates/tags.html:31 templates/backup/tags.html:30
msgid "by name"
msgstr ""
-#: templates/tags.html:31
+#: templates/tags.html:32 templates/backup/tags.html:31
msgid "sorted by frequency of tag use"
msgstr ""
-#: templates/tags.html:31
+#: templates/tags.html:32 templates/backup/tags.html:31
msgid "by popularity"
msgstr ""
-#: templates/tags.html:37
+#: templates/tags.html:38 templates/backup/tags.html:37
msgid "All tags matching query"
msgstr ""
-#: templates/tags.html:37
+#: templates/tags.html:38 templates/backup/tags.html:37
msgid "all tags - make this empty in english"
msgstr ""
-#: templates/tags.html:40
+#: templates/tags.html:41 templates/backup/tags.html:40
msgid "Nothing found"
msgstr ""
#: templates/unanswered.html:7 templates/unanswered.html.py:18
+#: templates/backup/unanswered.html:6 templates/backup/unanswered.html:17
+#: templates/tough/unanswered.html:5 templates/tough/unanswered.html.py:16
msgid "Unanswered questions"
msgstr ""
-#: templates/unanswered.html:20
-msgid "most recently asked questions"
-msgstr ""
-
#: templates/unanswered.html:97
#, python-format
msgid "have %(num_q)s unanswered questions"
msgstr ""
+"<div class=\"questions-count\">%(num_q)s</div><strong>unanswered</strong> "
+"questions"
-#: templates/unanswered.html:99
+#: templates/unanswered.html:99 templates/backup/questions.html:107
+#: templates/backup/unanswered.html:97
msgid "Have a total of"
msgstr ""
-#: templates/user_edit.html:6
+#: templates/user_edit.html:6 templates/backup/user_edit.html:4
msgid "Edit user profile"
msgstr ""
-#: templates/user_edit.html:19
+#: templates/user_edit.html:19 templates/backup/user_edit.html:17
msgid "edit profile"
msgstr ""
-#: templates/user_edit.html:31
+#: templates/user_edit.html:31 templates/backup/user_edit.html:29
msgid "image associated with your email address"
msgstr ""
-#: templates/user_edit.html:31
+#: templates/user_edit.html:31 templates/backup/user_edit.html:29
msgid "avatar"
msgstr ""
#: templates/user_edit.html:36 templates/user_info.html:31
+#: templates/backup/user_edit.html:34 templates/backup/user_info.html:30
msgid "Registered user"
msgstr ""
-#: templates/user_edit.html:82
+#: templates/user_edit.html:82 templates/backup/user_edit.html:80
msgid "Update"
msgstr ""
-#: templates/user_info.html:34
+#: templates/user_info.html:34 templates/backup/user_info.html:33
msgid "update profile"
msgstr ""
-#: templates/user_info.html:40
+#: templates/user_info.html:40 templates/backup/user_info.html:39
msgid "real name"
msgstr ""
@@ -1535,35 +2030,35 @@ msgstr ""
msgid "member for"
msgstr ""
-#: templates/user_info.html:50
+#: templates/user_info.html:50 templates/backup/user_info.html:49
msgid "last seen"
msgstr ""
-#: templates/user_info.html:56
+#: templates/user_info.html:56 templates/backup/user_info.html:55
msgid "user website"
msgstr ""
-#: templates/user_info.html:62
+#: templates/user_info.html:62 templates/backup/user_info.html:61
msgid "location"
msgstr ""
-#: templates/user_info.html:69
+#: templates/user_info.html:69 templates/backup/user_info.html:68
msgid "age"
msgstr ""
-#: templates/user_info.html:70
+#: templates/user_info.html:70 templates/backup/user_info.html:69
msgid "age unit"
msgstr ""
-#: templates/user_info.html:75
+#: templates/user_info.html:75 templates/backup/user_info.html:74
msgid "todays unused votes"
msgstr ""
-#: templates/user_info.html:76
+#: templates/user_info.html:76 templates/backup/user_info.html:75
msgid "votes left"
msgstr ""
-#: templates/user_stats.html:15
+#: templates/user_stats.html:15 templates/backup/user_stats.html:14
msgid "User questions"
msgstr ""
@@ -1572,94 +2067,87 @@ msgstr ""
msgid "the answer has been voted for %(vote_count)s times"
msgstr ""
-#: templates/user_stats.html:37
+#: templates/user_stats.html:37 templates/backup/user_stats.html:36
msgid "this answer has been selected as correct"
msgstr ""
-#: templates/user_stats.html:43
+#: templates/user_stats.html:43 templates/backup/user_stats.html:42
#, python-format
msgid "the answer has been commented %(answered_question.comment_count)s times"
msgstr ""
-#: templates/user_stats.html:56
+#: templates/user_stats.html:56 templates/backup/user_stats.html:55
msgid "votes total"
-msgstr ""
+msgstr "Votes"
-#: templates/user_stats.html:65
+#: templates/user_stats.html:65 templates/backup/user_stats.html:64
msgid "user has voted up this many times"
msgstr ""
-#: templates/user_stats.html:70
+#: templates/user_stats.html:70 templates/backup/user_stats.html:69
msgid "user voted down this many times"
msgstr ""
-#: templates/user_stats.html:84
+#: templates/user_stats.html:84 templates/backup/user_stats.html:83
msgid "Tags"
msgstr ""
-#: templates/user_stats.html:94
+#: templates/user_stats.html:94 templates/backup/user_stats.html:93
#, python-format
msgid "see other questions tagged '%(tag)s' "
msgstr ""
-#: templates/user_tabs.html:7
+#: templates/user_tabs.html:7 templates/backup/user_tabs.html:6
msgid "User profile"
msgstr ""
-#: templates/user_tabs.html:16
+#: templates/user_tabs.html:16 templates/backup/user_tabs.html:15
msgid "graph of user reputation"
msgstr ""
-#: templates/user_tabs.html:17
+#: templates/user_tabs.html:17 templates/backup/user_tabs.html:16
msgid "reputation history"
msgstr ""
-#: templates/user_tabs.html:24
+#: templates/user_tabs.html:24 templates/backup/user_tabs.html:23
msgid "favorites"
msgstr ""
-#: templates/user_tabs.html:29
+#: templates/user_tabs.html:29 templates/backup/user_tabs.html:28
msgid "settings"
msgstr ""
-#: templates/user_votes.html:14
-msgid "upvote"
-msgstr ""
-
-#: templates/user_votes.html:16
-msgid "downvote"
-msgstr ""
-
-#: templates/users.html:5 templates/users.html.py:23
+#: templates/users.html:6 templates/users.html.py:24
+#: templates/backup/users.html:5 templates/backup/users.html.py:23
msgid "Users"
msgstr ""
-#: templates/users.html:26
+#: templates/users.html:27 templates/backup/users.html:26
msgid "recent"
msgstr ""
-#: templates/users.html:27
+#: templates/users.html:28 templates/backup/users.html:27
msgid "oldest"
msgstr ""
-#: templates/users.html:28
+#: templates/users.html:29 templates/backup/users.html:28
msgid "by username"
msgstr ""
-#: templates/users.html:34
+#: templates/users.html:35 templates/backup/users.html:34
#, python-format
msgid "users matching query %(suser)s:"
msgstr ""
-#: templates/users.html:38
+#: templates/users.html:39 templates/backup/users.html:38
msgid "Nothing found."
msgstr ""
-#: templates/users_questions.html:11
+#: templates/users_questions.html:11 templates/backup/users_questions.html:10
msgid "this questions was selected as favorite"
msgstr ""
-#: templates/users_questions.html:33
+#: templates/users_questions.html:33 templates/backup/users_questions.html:32
msgid "this answer has been accepted to be correct"
msgstr ""
@@ -1686,7 +2174,7 @@ msgid "Email"
msgstr ""
#: templates/authopenid/changeemail.html:29
-#: templates/authopenid/signin.html:60
+#: templates/authopenid/signin.html:59
msgid "Password"
msgstr ""
@@ -1752,7 +2240,7 @@ msgid "This account already exists, please use another."
msgstr ""
#: templates/authopenid/complete.html:16 templates/authopenid/complete.html:29
-#: templates/authopenid/signin.html:43
+#: templates/authopenid/signin.html:42
msgid "Sorry, looks like we have some errors:"
msgstr ""
@@ -1788,7 +2276,7 @@ msgstr ""
msgid "Register"
msgstr ""
-#: templates/authopenid/complete.html:62 templates/authopenid/signin.html:62
+#: templates/authopenid/complete.html:62 templates/authopenid/signin.html:61
msgid "Forgot your password?"
msgstr ""
@@ -1885,6 +2373,8 @@ msgstr ""
#: templates/authopenid/signin.html:21
msgid "we support two login modes"
msgstr ""
+"You can log in either through one of these services or traditionally - using "
+"local username/password."
#: templates/authopenid/signin.html:26 templates/authopenid/signup.html:49
msgid "Login with your OpenID"
@@ -1892,49 +2382,53 @@ msgstr ""
#: templates/authopenid/signin.html:28
msgid "select openid provider"
-msgstr ""
+msgstr "1) Please select your id service provider."
#: templates/authopenid/signin.html:32
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."
-#: templates/authopenid/signin.html:58
+#: templates/authopenid/signin.html:57
msgid "Use login name and password"
msgstr ""
-#: templates/authopenid/signin.html:59
+#: templates/authopenid/signin.html:58
msgid "Login name"
msgstr ""
-#: templates/authopenid/signin.html:63
+#: templates/authopenid/signin.html:62
msgid "Create new acccount"
msgstr ""
-#: templates/authopenid/signin.html:72
+#: templates/authopenid/signin.html:71
msgid "Why use OpenID?"
msgstr ""
-#: templates/authopenid/signin.html:76
+#: templates/authopenid/signin.html:75
msgid "with openid it is easier"
-msgstr ""
+msgstr "With the OpenID you don't need to create new username and password."
-#: templates/authopenid/signin.html:79
+#: templates/authopenid/signin.html:78
msgid "reuse openid"
-msgstr ""
+msgstr "You can safely re-use the same login for all OpenID-enabled websites."
-#: templates/authopenid/signin.html:82
+#: templates/authopenid/signin.html:81
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:85
+#: templates/authopenid/signin.html:84
msgid "openid is supported open standard"
-msgstr ""
+msgstr "OpenID is based on an open standard, supported by many organizations."
-#: templates/authopenid/signin.html:89
+#: templates/authopenid/signin.html:88
msgid "Find out more"
msgstr ""
-#: templates/authopenid/signin.html:90
+#: templates/authopenid/signin.html:89
msgid "Get OpenID"
msgstr ""
@@ -1971,3 +2465,76 @@ msgstr ""
#: templates/authopenid/signup.html:46
msgid "Register with your OpenID"
msgstr ""
+
+#
+#: templates/backup/answer_edit_tips.html:3
+#: templates/backup/question_edit_tips.html:2
+msgid "editing tips"
+msgstr "Tips"
+
+#: templates/backup/questions.html:108
+msgid "number of questions"
+msgstr ""
+
+#: templates/backup/questions.html:110
+msgid "tagged with"
+msgstr ""
+
+#: templates/backup/questions.html:116
+msgid "whose title contains"
+msgstr ""
+
+#: templates/backup/questions.html:121
+msgid "number of questions end of sentence."
+msgstr ""
+
+#: templates/backup/questions.html:123
+msgid "Questions are sorted by <strong>entry date</strong>."
+msgstr ""
+
+#: templates/backup/questions.html:123
+msgid "Newest questions shown first."
+msgstr ""
+"Questions are sorted by <strong>entry date</strong>.Newest questions shown "
+"first."
+
+#: templates/backup/unanswered.html:98 templates/tough/unanswered.html:95
+msgid "number of <strong>unanswered</strong> questions"
+msgstr ""
+
+#: templates/backup/user_info.html:44
+msgid "member since"
+msgstr ""
+
+#: templates/backup/user_stats.html:36
+#, python-format
+msgid "the answer has been voted for %(answered_question.vote_count)s times"
+msgstr ""
+
+#: templates/tough/question_retag.html:2
+msgid "Revise tags"
+msgstr ""
+
+#: templates/tough/question_retag.html:37
+msgid "tags are requried"
+msgstr ""
+
+#: templates/tough/question_retag.html:38
+msgid "up to 5 tags, less than 20 characters each"
+msgstr ""
+
+#: templates/tough/question_retag.html:51
+msgid "Change tags"
+msgstr ""
+
+#: templates/tough/question_retag.html:74
+msgid "Change now"
+msgstr ""
+
+#: templates/tough/question_retag.html:85
+msgid "Why use and modify tags?"
+msgstr ""
+
+#: templates/tough/question_retag.html:96
+msgid "tag editors receive special awards from the community"
+msgstr ""
diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo
deleted file mode 100644
index 8c359972..00000000
--- a/locale/es/LC_MESSAGES/django.mo
+++ /dev/null
Binary files differ
diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po
index 93cfdfe4..fe0aab7c 100644
--- a/locale/es/LC_MESSAGES/django.po
+++ b/locale/es/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-07-28 15:57+0000\n"
+"POT-Creation-Date: 2009-07-23 01:11-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,120 +16,128 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: settings.py:12
+#: settings.py:27
msgid "account/"
-msgstr ""
+msgstr "cuenta/"
-#: settings.py:12 django_authopenid/urls.py:9 django_authopenid/urls.py:11
+#: settings.py:27 django_authopenid/urls.py:9 django_authopenid/urls.py:11
msgid "signin/"
-msgstr ""
+msgstr "ingresar/"
#: django_authopenid/forms.py:67 django_authopenid/views.py:93
msgid "i-names are not supported"
-msgstr ""
+msgstr "i-names no son soportados"
#: django_authopenid/forms.py:102 django_authopenid/forms.py:207
msgid ""
"Usernames can only contain letters, numbers and "
"underscores"
msgstr ""
+"Los nombres de usuario solo pueden contener letras, números y guión bajo"
#: django_authopenid/forms.py:109
msgid ""
"This username does not exist in our database. Please "
"choose another."
msgstr ""
+"Este nombre de usuario no existe en nuestra base de datos. Por favor elija "
+"otro."
#: django_authopenid/forms.py:126 django_authopenid/forms.py:231
msgid ""
"Please enter a valid username and password. Note that "
"both fields are case-sensitive."
msgstr ""
+"Por favor ingrese un usuario y contraseña validos. Ambos campos son "
+"sensibles a mayúsculas y minúsculas."
#: django_authopenid/forms.py:130 django_authopenid/forms.py:235
msgid "This account is inactive."
-msgstr ""
+msgstr "Esta cuenta esta inactiva."
#: django_authopenid/forms.py:158
msgid "invalid user name"
-msgstr ""
+msgstr "nombre de usuario no valido"
#: django_authopenid/forms.py:160
msgid "sorry, this name can not be used, please try another"
msgstr ""
+"perdón, pero este nombre de usuario no puede ser usado, intente con otro"
#: django_authopenid/forms.py:162
msgid "username too short"
-msgstr ""
+msgstr "nombre de usuario muy corto"
#: django_authopenid/forms.py:170 django_authopenid/forms.py:171
msgid "this name is already in use - please try anoter"
-msgstr ""
+msgstr "este nombre ya está tomado - por favor intente con otro"
#: django_authopenid/forms.py:184
msgid ""
"This email is already registered in our database. Please "
"choose another."
msgstr ""
+"Este email ya está registrado en nuestra base de datos. Por favor, intente "
+"con otro."
#: django_authopenid/forms.py:214
msgid ""
"This username don't exist. Please choose another."
-msgstr ""
+msgstr "Este nombre de usuario no existe, por favor ingrese otro."
#: django_authopenid/forms.py:253
msgid "choose a username"
-msgstr ""
+msgstr "elija un nombre de usuario"
#: django_authopenid/forms.py:255 templates/authopenid/signup.html:36
msgid "your email address"
-msgstr ""
+msgstr "su email (correo electrónico)"
#: django_authopenid/forms.py:257 templates/authopenid/signup.html:37
msgid "choose password"
-msgstr ""
+msgstr "elija una contraseña"
#: django_authopenid/forms.py:259 templates/authopenid/signup.html:38
msgid "retype password"
-msgstr ""
+msgstr "re-ingrese la contraseña"
#: django_authopenid/forms.py:330
msgid ""
"Old password is incorrect. Please enter the correct "
"password."
-msgstr ""
+msgstr "La antigua contraseña es incorrecta. Por favor ingrese la correcta"
#: django_authopenid/forms.py:342
msgid "new passwords do not match"
-msgstr ""
+msgstr "la nueva contraseña no coincide"
#: django_authopenid/forms.py:434
msgid "Incorrect username."
-msgstr ""
+msgstr "Nombre de usuario incorrecto"
#: django_authopenid/urls.py:10
msgid "signout/"
-msgstr ""
+msgstr "salir/"
#: django_authopenid/urls.py:11
msgid "complete/"
-msgstr ""
+msgstr "completado/"
#: django_authopenid/urls.py:13
msgid "register/"
-msgstr ""
+msgstr "registrarse/"
#: django_authopenid/urls.py:14
msgid "signup/"
-msgstr ""
+msgstr "registrarse/"
#: django_authopenid/urls.py:16
msgid "sendpw/"
-msgstr ""
+msgstr "enviarcontrasena/"
#: django_authopenid/urls.py:26
msgid "delete/"
-msgstr ""
+msgstr "borrar/"
#: django_authopenid/views.py:99
#, python-format
@@ -138,50 +146,50 @@ msgstr ""
#: django_authopenid/views.py:366
msgid "Welcome"
-msgstr ""
+msgstr "Bienvenido"
#: django_authopenid/views.py:456
msgid "Password changed."
-msgstr ""
+msgstr "Contraseña modificada"
#: django_authopenid/views.py:488
msgid "Email changed."
-msgstr ""
+msgstr "Email modificado."
#: django_authopenid/views.py:519 django_authopenid/views.py:671
#, python-format
msgid "No OpenID %s found associated in our database"
-msgstr ""
+msgstr "La OpenID %s no esta asociada en nuestra base de datos"
#: django_authopenid/views.py:523 django_authopenid/views.py:678
#, python-format
msgid "The OpenID %s isn't associated to current user logged in"
-msgstr ""
+msgstr "La OpenID %s no esta asociada al usuario actualmente autenticado"
#: django_authopenid/views.py:531
msgid "Email Changed."
-msgstr ""
+msgstr "Email modificado"
#: django_authopenid/views.py:606
msgid "This OpenID is already associated with another account."
-msgstr ""
+msgstr "Esta OpenID ya está asociada a otra cuenta."
#: django_authopenid/views.py:611
#, python-format
msgid "OpenID %s is now associated with your account."
-msgstr ""
+msgstr "La OpenID %s está ahora asociada con tu cuenta."
#: django_authopenid/views.py:681
msgid "Account deleted."
-msgstr ""
+msgstr "Cuenta borrada."
#: django_authopenid/views.py:721
msgid "Request for new password"
-msgstr ""
+msgstr "Pedir nueva contraseña"
#: django_authopenid/views.py:734
msgid "A new password has been sent to your email address."
-msgstr ""
+msgstr "Una nueva contraseña ha sido enviada a tu cuenta de Email."
#: django_authopenid/views.py:764
#, python-format
@@ -189,995 +197,1379 @@ msgid ""
"Could not change password. Confirmation key '%s' is not "
"registered."
msgstr ""
+"No se ha podido modificar la contraseña. La clave de confirmación '%s' no "
+"está registrada"
#: django_authopenid/views.py:773
msgid ""
"Can not change password. User don't exist anymore in our "
"database."
msgstr ""
+"No se puede cambiar la contraseña. El usuario no existe más en nuestra base "
+"de datos."
#: django_authopenid/views.py:782
#, python-format
msgid "Password changed for %s. You may now sign in."
-msgstr ""
+msgstr "Contraseña cambiada por %s. Ahora puedes ingresar."
#: forum/const.py:8
msgid "duplicate question"
-msgstr ""
+msgstr "pregunta duplicada"
#: forum/const.py:9
msgid "question if off-topic or not relevant"
-msgstr ""
+msgstr "pregunta esta fuera de tema o no es relevante"
#: forum/const.py:10
msgid "too subjective and argumentative"
-msgstr ""
+msgstr "demasiado subjetiva o argumentativa"
#: forum/const.py:11
msgid "is not an answer to the question"
-msgstr ""
+msgstr "no es una respuesta a la pregunta"
#: forum/const.py:12
msgid "the question is answered, right answer was accepted"
-msgstr ""
+msgstr "la pregunta esta respondida, se ha aceptado la respuesta correcta"
#: forum/const.py:13
msgid "problem is not reproducible or outdated"
-msgstr ""
+msgstr "el problema no es reproducible o caducó"
#: forum/const.py:15
msgid "question contains offensive inappropriate, or malicious remarks"
-msgstr ""
+msgstr "la pregunta contiene frases ofensivas, inapropiadas o maliciosas."
#: forum/const.py:16
msgid "spam or advertising"
-msgstr ""
+msgstr "spam o publicidad"
#: forum/const.py:56
msgid "question"
-msgstr ""
+msgstr "pregunta"
#: forum/const.py:57 templates/book.html:110
msgid "answer"
-msgstr ""
+msgstr "resputa"
#: forum/const.py:58
msgid "commented question"
-msgstr ""
+msgstr "pregunta comentada"
#: forum/const.py:59
msgid "commented answer"
-msgstr ""
+msgstr "respuesta comentada"
#: forum/const.py:60
msgid "edited question"
-msgstr ""
+msgstr "pregunta editada"
#: forum/const.py:61
msgid "edited answer"
-msgstr ""
+msgstr "respuesta editada"
#: forum/const.py:62
msgid "received award"
-msgstr ""
+msgstr "premio recibido"
#: forum/const.py:63
msgid "marked best answer"
-msgstr ""
+msgstr "marcada como mejor respuesta"
#: forum/const.py:64
msgid "upvoted"
-msgstr ""
+msgstr "votada positivo"
#: forum/const.py:65
msgid "downvoted"
-msgstr ""
+msgstr "votada negativo"
#: forum/const.py:66
msgid "canceled vote"
-msgstr ""
+msgstr "voto cancelado"
#: forum/const.py:67
msgid "deleted question"
-msgstr ""
+msgstr "pregunta borrada"
#: forum/const.py:68
msgid "deleted answer"
-msgstr ""
+msgstr "respuesta borrada"
#: forum/const.py:69
msgid "marked offensive"
-msgstr ""
+msgstr "marcada como ofensiva"
#: forum/const.py:70
msgid "updated tags"
-msgstr ""
+msgstr "etiquetas actualizadas"
#: forum/const.py:71
msgid "selected favorite"
-msgstr ""
+msgstr "seleccionada como favorita"
#: forum/const.py:72
msgid "completed user profile"
-msgstr ""
+msgstr "completó perfil de usuario"
#: forum/const.py:83
msgid "[closed]"
-msgstr ""
+msgstr "[cerrada]"
#: forum/const.py:84
msgid "[deleted]"
-msgstr ""
+msgstr "[borrada]"
#: forum/const.py:85
msgid "initial version"
-msgstr ""
+msgstr "versión inicial"
#: forum/const.py:86
msgid "retagged"
-msgstr ""
+msgstr "re-etiquetada"
-#: forum/feed.py:17
+#: forum/feed.py:17 templates/base.html:7 templates/base_content.html:6
+#: templates/faq.html:25 templates/faq.html.py:108 templates/tough/faq.html:23
+#: templates/tough/faq.html.py:106 templates/tough/question_retag.html:89
msgid "site title"
-msgstr ""
+msgstr "titulo del sitio"
#: forum/feed.py:17
msgid " - "
-msgstr ""
+msgstr " - "
-#: forum/feed.py:17
+#: forum/feed.py:17 templates/base.html:7 templates/base_content.html:6
msgid "site slogan"
-msgstr ""
+msgstr " slogan del sitio"
#: forum/feed.py:17
msgid "latest questions"
-msgstr ""
+msgstr "últimas preguntas"
-#: forum/feed.py:20
+#: forum/feed.py:20 templates/index.html:8
msgid "meta site content"
-msgstr ""
+msgstr "meta descripción"
#: forum/feed.py:22
msgid "copyright message"
-msgstr ""
+msgstr "mensaje de copyright"
-#: forum/forms.py:14 templates/question_edit_tips.html:31
+#: forum/forms.py:14 templates/answer_edit_tips.html:34
+#: templates/answer_edit_tips.html.py:39 templates/question_edit_tips.html:31
#: templates/question_edit_tips.html:36
msgid "title"
-msgstr ""
+msgstr "titulo"
#: forum/forms.py:15
msgid "please enter a descriptive title for your question"
-msgstr ""
+msgstr "ingrese un titulo descriptivo para su pregunta"
#: forum/forms.py:20
msgid "title must be > 10 characters"
-msgstr ""
+msgstr "el titulo debe tener al menos 10 caracteres"
#: forum/forms.py:29
msgid "content"
-msgstr ""
+msgstr "contenido"
#: forum/forms.py:35
msgid "question content must be > 10 characters"
-msgstr ""
+msgstr "el contenido de la pregunta debe ser al menos de 10 caracteres"
#: forum/forms.py:45 templates/header.html:30 templates/header.html.py:61
msgid "tags"
-msgstr ""
+msgstr "etiquetas"
#: forum/forms.py:46
msgid "please use space to separate tags (this enables autocomplete feature)"
msgstr ""
+"por favor utilice espacio para separar las etiquetas (esto habilitael auto-"
+"completado)"
#: forum/forms.py:53
msgid "tags are required"
-msgstr ""
+msgstr "las etiquetas son requeridas"
#: forum/forms.py:57
msgid "please use 5 tags or less"
-msgstr ""
+msgstr "por favor use 5 o menos etiquetas"
#: forum/forms.py:60
msgid "tags must be shorter than 20 characters"
-msgstr ""
+msgstr "las etiquetas deben ser menores a 20 caracteres"
#: forum/forms.py:64
msgid ""
"please use following characters in tags: letters 'a-z', numbers, and "
"characters '.-_#'"
msgstr ""
+"por favor use solo los siguientes caracteres en los nombres de etiquetas: "
+"letras 'a-z', números y caracteres '.-_#'"
#: forum/forms.py:74 templates/index.html:56 templates/question.html:196
-#: templates/question.html.py:377 templates/unanswered.html:48
-#: templates/unanswered.html.py:60
+#: templates/question.html.py:377 templates/questions.html:58
+#: templates/questions.html.py:70 templates/unanswered.html:48
+#: templates/unanswered.html.py:60 templates/tough/unanswered.html:46
+#: templates/tough/unanswered.html.py:58
msgid "community wiki"
-msgstr ""
+msgstr "wiki de comunidad"
#: forum/forms.py:75
msgid ""
"if you choose community wiki option, the question and answer do not generate "
"points and name of author will not be shown"
msgstr ""
+"si marca la opción 'wiki de comunidad', la pregunta y respuestas no generan "
+"puntos y el nombre del autor no será mostrado"
#: forum/forms.py:84
msgid "update summary:"
-msgstr ""
+msgstr "resumen de modificación"
#: forum/forms.py:85
msgid ""
"enter a brief summary of your revision (e.g. fixed spelling, grammar, "
"improved style, this field is optional)"
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:160
msgid "this email does not have to be linked to gravatar"
-msgstr ""
+msgstr "este email no tiene porque estar asociado a un Gravatar"
#: forum/forms.py:161
msgid "Real name"
-msgstr ""
+msgstr "Nombre real"
#: forum/forms.py:162
msgid "Website"
-msgstr ""
+msgstr "Sitio Web"
#: forum/forms.py:163
msgid "Location"
-msgstr ""
+msgstr "Ubicación"
#: forum/forms.py:164
msgid "Date of birth"
-msgstr ""
+msgstr "Fecha de nacimiento"
#: forum/forms.py:164
msgid "will not be shown, used to calculate age, format: YYYY-MM-DD"
-msgstr ""
+msgstr "no será mostrado, usado para calcular la edad. Formato: YYY-MM-DD"
-#: forum/forms.py:165 templates/authopenid/settings.html:20
+#: forum/forms.py:165 templates/base.html:64
+#: templates/authopenid/settings.html:20
msgid "Profile"
-msgstr ""
+msgstr "Perfil"
#: forum/forms.py:190 forum/forms.py:191
msgid "this email has already been registered, please use another one"
-msgstr ""
+msgstr "este email ya ha sido registrado, por favor use otro"
-#: forum/models.py:316 templates/badges.html:50
+#: forum/models.py:316 templates/badges.html:51
msgid "gold"
-msgstr ""
+msgstr "oro"
-#: forum/models.py:317 templates/badges.html:58
+#: forum/models.py:317 templates/badges.html:59
msgid "silver"
-msgstr ""
+msgstr "plata"
-#: forum/models.py:318 templates/badges.html:65
+#: forum/models.py:318 templates/badges.html:66
msgid "bronze"
-msgstr ""
+msgstr "bronze"
-#: forum/user.py:17 templates/user_tabs.html:7
+#: forum/user.py:16 templates/user_tabs.html:7
msgid "overview"
-msgstr ""
+msgstr "vista general"
-#: forum/user.py:18
+#: forum/user.py:17
msgid "user profile"
-msgstr ""
+msgstr "perfil de usuario"
-#: forum/user.py:19
+#: forum/user.py:18
msgid "user profile overview"
-msgstr ""
+msgstr "vista general del perfil de usuario"
-#: forum/user.py:25 templates/user_tabs.html:9
+#: forum/user.py:24 templates/user_tabs.html:9
msgid "recent activity"
-msgstr ""
+msgstr "actividades recientes"
-#: forum/user.py:26
+#: forum/user.py:25
msgid "recent user activity"
-msgstr ""
+msgstr "actividades recientes del usuario"
-#: forum/user.py:27
+#: forum/user.py:26
msgid "profile - recent activity"
-msgstr ""
+msgstr "perfil - actividades recientes"
-#: forum/user.py:34 templates/user_tabs.html:13
+#: forum/user.py:33 templates/user_tabs.html:13
msgid "responses"
-msgstr ""
+msgstr "respuestas"
-#: forum/user.py:35 templates/user_tabs.html:12
+#: forum/user.py:34 templates/user_tabs.html:12
msgid "comments and answers to others questions"
-msgstr ""
+msgstr "comentarios y respuestas a preguntas de otros"
-#: forum/user.py:36
+#: forum/user.py:35
msgid "profile - responses"
-msgstr ""
+msgstr "perfil - respuestas"
-#: forum/user.py:43 templates/user_info.html:23 templates/users.html:25
+#: forum/user.py:42 templates/user_info.html:23 templates/users.html:26
msgid "reputation"
-msgstr ""
+msgstr "reputación"
-#: forum/user.py:44
+#: forum/user.py:43
msgid "user reputation in the community"
-msgstr ""
+msgstr "reputación del usuario en la comunidad"
-#: forum/user.py:45
+#: forum/user.py:44
msgid "profile - user reputation"
-msgstr ""
+msgstr "perfil - reputación del usuario"
-#: forum/user.py:51
+#: forum/user.py:50
msgid "favorite questions"
-msgstr ""
+msgstr "preguntas favoritas"
-#: forum/user.py:52
+#: forum/user.py:51
msgid "users favorite questions"
-msgstr ""
+msgstr "preguntas favoritas del usuario"
-#: forum/user.py:53
+#: forum/user.py:52
msgid "profile - favorite questions"
-msgstr ""
+msgstr "perfil - preguntas favoritas"
-#: forum/user.py:60 templates/user_tabs.html:20
+#: forum/user.py:59 templates/user_tabs.html:20
msgid "casted votes"
-msgstr ""
+msgstr "votos"
-#: forum/user.py:61 templates/user_tabs.html:20
+#: forum/user.py:60 templates/user_tabs.html:20
msgid "user vote record"
-msgstr ""
+msgstr "historial de votación"
-#: forum/user.py:62
+#: forum/user.py:61
msgid "profile - votes"
-msgstr ""
+msgstr "perfil - votos"
-#: forum/user.py:69
+#: forum/user.py:68
msgid "preferences"
-msgstr ""
+msgstr "preferencias"
-#: forum/user.py:70 templates/user_tabs.html:28
+#: forum/user.py:69 templates/user_tabs.html:28
msgid "user preference settings"
-msgstr ""
+msgstr "preferencias del usuario"
-#: forum/user.py:71
+#: forum/user.py:70
msgid "profile - user preferences"
-msgstr ""
+msgstr "perfil - preferencia de "
-#: forum/views.py:1726
+#: forum/views.py:1730
msgid "uploading images is limited to users with >60 reputation points"
-msgstr ""
+msgstr "para subir imagenes debes tener más de 60 puntos de reputación"
-#: forum/views.py:1728
+#: forum/views.py:1732
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:1730
+#: forum/views.py:1734
#, python-format
msgid "maximum upload file size is %sK"
-msgstr ""
+msgstr "tamaño máximo permitido es archivo %sK"
-#: forum/views.py:1732
+#: forum/views.py:1736
#, python-format
msgid ""
"Error uploading file. Please contact the site administrator. Thank you. %s"
msgstr ""
+"Error al subir el archivo. Por favor, contacte al administrador. Gracias. %s"
#: forum/templatetags/extra_tags.py:139 forum/templatetags/extra_tags.py:168
#: templates/header.html:33
msgid "badges"
-msgstr ""
+msgstr "distinciones"
#: forum/templatetags/extra_tags.py:140 forum/templatetags/extra_tags.py:167
msgid "reputation points"
-msgstr ""
+msgstr "puntos de reputación"
#: forum/templatetags/extra_tags.py:221
msgid " ago"
-msgstr ""
+msgstr " atras"
#: templates/404.html:24
msgid "Sorry, could not find the page you requested."
-msgstr ""
+msgstr "Disculpe, no se pudo encontrar la página que solicito."
#: templates/404.html:26
msgid "This might have happened for the following reasons:"
-msgstr ""
+msgstr "Esto puede haber sucedido por alguno de los siguientes motivos:"
#: templates/404.html:28
msgid "this question or answer has been deleted;"
-msgstr ""
+msgstr "esta pregunta o respuesta ha sido borrada;"
#: templates/404.html:29
msgid "url has error - please check it;"
-msgstr ""
+msgstr "la url tiene un error - por favor compruebelo;"
#: templates/404.html:30
msgid ""
"the page you tried to visit is protected or you don't have sufficient "
"points, see"
msgstr ""
+"La pagina que intentas acceder esta protegida o no tienes los puntos de "
+"reputación suficientes, ver"
#: templates/404.html:31
msgid "if you believe this error 404 should not have occured, please"
-msgstr ""
+msgstr "si consideras que este error 404 no debería haber sucedido, por favor"
#: templates/404.html:32
msgid "report this problem"
-msgstr ""
+msgstr "reporta este problema"
#: templates/404.html:41 templates/500.html:27
msgid "back to previous page"
-msgstr ""
+msgstr "volver a la página siguiente"
#: templates/404.html:42
msgid "see all questions"
-msgstr ""
+msgstr "ver todas las preguntas"
#: templates/404.html:43
msgid "see all tags"
-msgstr ""
+msgstr "ver todas las tags"
#: templates/500.html:24
msgid "system error log is recorded, error will be fixed as soon as possible"
msgstr ""
+"el error del sistema ha sido registrado, y será solucionado lo antes postible"
#: templates/500.html:25
msgid "please report the error to the site administrators if you wish"
-msgstr ""
+msgstr "por favor reportar el error al administrador de ser posible"
#: templates/500.html:28
msgid "see latest questions"
-msgstr ""
+msgstr "ver ultimas preguntas"
#: templates/500.html:29
msgid "see tags"
-msgstr ""
+msgstr "ver tags"
+
+#: templates/about.html:6 templates/about.html.py:11
+msgid "About"
+msgstr "Acerca de"
#: templates/answer_edit.html:4 templates/answer_edit.html.py:47
msgid "Edit answer"
-msgstr ""
+msgstr "Editar respuesta"
#: templates/answer_edit.html:24 templates/answer_edit.html.py:27
#: templates/ask.html:25 templates/ask.html.py:28 templates/question.html:37
#: templates/question.html.py:40 templates/question_edit.html:27
msgid "hide preview"
-msgstr ""
+msgstr "ocultar previsualización"
#: templates/answer_edit.html:27 templates/ask.html:28
#: templates/question.html:40 templates/question_edit.html:27
msgid "show preview"
-msgstr ""
+msgstr "ver previsualización"
#: templates/answer_edit.html:47 templates/question_edit.html:65
#: templates/revisions_answer.html:36 templates/revisions_question.html:36
+#: templates/tough/question_retag.html:51
msgid "back"
-msgstr ""
+msgstr "volver"
#: templates/answer_edit.html:52 templates/question_edit.html:70
#: templates/revisions_answer.html:47 templates/revisions_question.html:47
msgid "revision"
-msgstr ""
+msgstr "revisión"
#: templates/answer_edit.html:55 templates/question_edit.html:74
msgid "select revision"
-msgstr ""
+msgstr "seleccionar revisión"
#: templates/answer_edit.html:62 templates/ask.html:81
#: templates/question.html:447 templates/question_edit.html:91
msgid "Toggle the real time Markdown editor preview"
-msgstr ""
+msgstr "Activar la visualización en tiempo real de Markdown"
#: templates/answer_edit.html:62 templates/ask.html:81
#: templates/question.html:447 templates/question_edit.html:91
msgid "toggle preview"
-msgstr ""
+msgstr "Activar previsualización"
#: templates/answer_edit.html:73 templates/question_edit.html:119
msgid "Save edit"
-msgstr ""
+msgstr "Guardar la edición"
#: templates/answer_edit.html:74 templates/close.html:29
#: templates/question_edit.html:120 templates/reopen.html:30
-#: templates/user_edit.html:83
+#: templates/user_edit.html:83 templates/tough/question_retag.html:75
msgid "Cancel"
-msgstr ""
+msgstr "Cancelar"
+
+#: templates/answer_edit_tips.html:4
+msgid "answer tips"
+msgstr "sugerencias sobre respuestas"
+
+#: templates/answer_edit_tips.html:7
+msgid "please make your answer relevant to this community"
+msgstr "por favor, haz que tu respuesta sea relevante a esta comunidad"
+
+#: templates/answer_edit_tips.html:10
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr "intenta dar una respuesta, más que entablar un debate o discusión"
+
+#: templates/answer_edit_tips.html:13
+msgid "please try to provide details"
+msgstr "por favor, intenta brindar detalles"
+
+#: templates/answer_edit_tips.html:16 templates/question_edit_tips.html:13
+msgid "be clear and concise"
+msgstr "ser claro y conciso"
+
+#: templates/answer_edit_tips.html:19 templates/question_edit_tips.html:16
+msgid "see frequently asked questions"
+msgstr "ver preguntas frecuentes"
+
+#: templates/answer_edit_tips.html:25 templates/question_edit_tips.html:22
+msgid "Markdown tips"
+msgstr "sugerencias de Markdown"
+
+#: templates/answer_edit_tips.html:28 templates/question_edit_tips.html:25
+msgid "*italic* or __italic__"
+msgstr "*itálica* o __itálica__"
+
+#: templates/answer_edit_tips.html:31 templates/question_edit_tips.html:28
+msgid "**bold** or __bold__"
+msgstr "**negrita** o __negrita__"
+
+#: templates/answer_edit_tips.html:34 templates/question_edit_tips.html:31
+msgid "link"
+msgstr "enlace"
+
+#: templates/answer_edit_tips.html:34 templates/answer_edit_tips.html.py:39
+#: templates/question_edit_tips.html:31 templates/question_edit_tips.html:36
+msgid "text"
+msgstr "texto"
+
+#: templates/answer_edit_tips.html:39 templates/question_edit_tips.html:36
+msgid "image"
+msgstr "imagen"
+
+#: templates/answer_edit_tips.html:43 templates/question_edit_tips.html:40
+msgid "numbered list:"
+msgstr "lista numerada"
+
+#: templates/answer_edit_tips.html:48 templates/question_edit_tips.html:45
+msgid "basic HTML tags are also supported"
+msgstr "etiquetas básicas de HTML permitidas"
+
+#: templates/answer_edit_tips.html:51 templates/question_edit_tips.html:48
+msgid "learn more about Markdown"
+msgstr "aprender mas sobre Markdown"
#: templates/ask.html:4 templates/ask.html.py:60
msgid "Ask a question"
-msgstr ""
+msgstr "Hacer una pregunta"
#: templates/ask.html:106
msgid "Use"
-msgstr ""
+msgstr "Usar"
#: templates/ask.html:106
msgid "learn more about OpenID"
-msgstr ""
+msgstr "aprender mas sobre OpenID"
#: templates/ask.html:106 templates/authopenid/signin.html:35
#: templates/authopenid/signin.html:61
msgid "Login"
-msgstr ""
+msgstr "Ingresar"
#: templates/ask.html:109
msgid "Get your own "
-msgstr ""
+msgstr "Obtiene tu propio "
#: templates/ask.html:117 templates/authopenid/sendpw.html:27
msgid "User name"
-msgstr ""
+msgstr "Nombre de usuario"
#: templates/ask.html:120
msgid "Email: (won't be shown to anyone)"
-msgstr ""
+msgstr "Email: (no será mostrado a nadie)"
#: templates/ask.html:127
msgid "Ask your question"
-msgstr ""
+msgstr "Haz tu pregunta"
#: templates/badge.html:6 templates/badge.html.py:17
msgid "Badge"
-msgstr ""
+msgstr "Distinción"
#: templates/badge.html:26
msgid "The users have been awarded with badges:"
-msgstr ""
+msgstr "Usuarios han sido galardonados con distinciones:"
-#: templates/badges.html:5
+#: templates/badges.html:6
msgid "Badges summary"
-msgstr ""
+msgstr "Resumen de distinciones"
-#: templates/badges.html:16 templates/user_stats.html:113
+#: templates/badges.html:17 templates/user_stats.html:113
msgid "Badges"
-msgstr ""
+msgstr "Distinciones"
-#: templates/badges.html:20
+#: templates/badges.html:21
msgid ""
"Community gives you awards for your questions, answers and votes. Below is "
"the list of available badges and number of times each type of badge has been "
"awarded."
msgstr ""
+"La comunidad te condecora con distinciones por tus preguntas, respuestas y "
+"votos. Debajo esta la lista de las distinciones disponibles y la cantidad de "
+"veces que han sido asignadas."
-#: templates/badges.html:47
+#: templates/badges.html:48
msgid "Community badges"
-msgstr ""
+msgstr "Distinciones de la comunidad"
-#: templates/badges.html:53
+#: templates/badges.html:54
msgid ""
"Gold badge is very rare. To obtain it you have to show profound knowledge "
"and ability in addition to actively participating in the community. Gold "
"badge is the highest award in this community."
msgstr ""
+"Las distinciones de Oro son excepcionales. Para obtenerla debes demostrar un "
+"profundo conocimiento y habilidad además de participar activamente en la "
+"comunidad. La distinción de Oro es la condecoración máxima en esta comunidad"
-#: templates/badges.html:61
+#: templates/badges.html:62
msgid ""
"Obtaining silver badge requires significant patience. If you got one, you've "
"very significantly contributed to this community"
msgstr ""
+"Obtener una distinción de Plata requiere de paciencia. Si has logrado una, "
+"quiere decir que haz significativamente aportado a esta comunidad."
-#: templates/badges.html:64
+#: templates/badges.html:65
msgid "bronze badge: often given as a special honor"
msgstr ""
+"distinción de bronce: con frecuencia entregada como reconocimiento especial."
-#: templates/badges.html:68
+#: templates/badges.html:69
msgid ""
"If you are active in this community, you will get this medal - still it is a "
"special honor."
msgstr ""
+"Si eres un usuario activo de esta comunidad, recibirás esta distinción - de "
+"todas maneras es un honor especial."
-#: templates/base.html:61 templates/base_content.html:60
-msgid "congratulations, community gave you a badge"
-msgstr ""
+#: templates/base.html:62
+#, fuzzy
+msgid "Congratulations! You have new badges: "
+msgstr "felicitaciones, la comunidad te ha otorgado una distinción"
-#: templates/base.html:63 templates/base_content.html:62
-msgid "profile"
-msgstr ""
+#: templates/base.html:63
+#, fuzzy
+msgid "go to see"
+msgstr "OK para cerrar"
#: templates/base_content.html:61
+msgid "congratulations, community gave you a badge"
+msgstr "felicitaciones, la comunidad te ha otorgado una distinción"
+
+#: templates/base_content.html:62
msgid "see"
-msgstr ""
+msgstr "ver"
+
+#: templates/base_content.html:63
+msgid "profile"
+msgstr "perfil"
#: templates/book.html:7
msgid "reading channel"
-msgstr ""
+msgstr "canal de lectura"
#: templates/book.html:26
msgid "[author]"
-msgstr ""
+msgstr "[autor]"
#: templates/book.html:30
msgid "[publisher]"
-msgstr ""
+msgstr "[editorial]"
#: templates/book.html:34
msgid "[publication date]"
-msgstr ""
+msgstr "[fecha de publicación]"
#: templates/book.html:38
msgid "[price]"
-msgstr ""
+msgstr "[precio]"
#: templates/book.html:39
msgid "currency unit"
-msgstr ""
+msgstr "unidad de moneda"
#: templates/book.html:42
msgid "[pages]"
-msgstr ""
+msgstr "[páginas]"
#: templates/book.html:43
msgid "pages abbreviation"
-msgstr ""
+msgstr "abreviación de páginas"
#: templates/book.html:46
msgid "[tags]"
-msgstr ""
+msgstr "[etiquetas]"
#: templates/book.html:56
msgid "author blog"
-msgstr ""
+msgstr "blog del autor"
#: templates/book.html:62
msgid "book directory"
-msgstr ""
+msgstr "directorio del libro"
#: templates/book.html:66
msgid "buy online"
-msgstr ""
+msgstr "comprar en-linea"
#: templates/book.html:79
msgid "reader questions"
-msgstr ""
+msgstr "pregunta de lector"
#: templates/book.html:82
msgid "ask the author"
-msgstr ""
+msgstr "preguntar al autor"
#: templates/book.html:88 templates/book.html.py:93
#: templates/users_questions.html:17
msgid "this question was selected as favorite"
-msgstr ""
+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:17
msgid "number of times"
-msgstr ""
+msgstr "numero de veces"
-#: templates/book.html:105 templates/index.html:47
+#: templates/book.html:105 templates/index.html:47 templates/questions.html:46
#: templates/unanswered.html:37 templates/users_questions.html:30
+#: templates/tough/unanswered.html:35
msgid "votes"
-msgstr ""
+msgstr "votos"
#: templates/book.html:108
msgid "the answer has been accepted to be correct"
-msgstr ""
+msgstr "la respuesta ha sido aceptada como correcta"
-#: templates/book.html:115 templates/index.html:48
+#: templates/book.html:115 templates/index.html:48 templates/questions.html:47
#: templates/unanswered.html:38 templates/users_questions.html:40
+#: templates/tough/unanswered.html:36
msgid "views"
-msgstr ""
+msgstr "vistas"
#: templates/book.html:125 templates/index.html:68 templates/question.html:112
-#: templates/question.html.py:479 templates/tags.html:46
+#: templates/question.html.py:479 templates/questions.html:84
+#: templates/questions.html.py:149 templates/tags.html:47
#: templates/unanswered.html:75 templates/unanswered.html.py:109
-#: templates/users_questions.html:52
+#: templates/users_questions.html:52 templates/tough/unanswered.html:72
+#: templates/tough/unanswered.html:105
msgid "using tags"
-msgstr ""
+msgstr "usando etiquetas"
#: templates/book.html:147
msgid "subscribe to book RSS feed"
-msgstr ""
+msgstr "suscribirse al RSS del libro"
-#: templates/book.html:147 templates/index.html:115
+#: templates/book.html:147 templates/index.html:116
msgid "subscribe to the questions feed"
-msgstr ""
+msgstr "suscribirse al agregado de noticias"
#: templates/close.html:6 templates/close.html.py:16
msgid "Close question"
-msgstr ""
+msgstr "Cerrar pregunta"
#: templates/close.html:19
msgid "Close the question"
-msgstr ""
+msgstr "Cerrar la pregunta"
#: templates/close.html:25
msgid "Reasons"
-msgstr ""
+msgstr "Razón"
#: templates/close.html:28
msgid "OK to close"
+msgstr "OK para cerrar"
+
+#: templates/faq.html:11 templates/tough/faq.html:9
+msgid "Frequently Asked Questions "
+msgstr "Preguntas Frecuentes"
+
+#: templates/faq.html:15 templates/tough/faq.html:13
+msgid "What kinds of questions can I ask here?"
+msgstr "¿Qué clase de preguntas puedo hacer aquí?"
+
+#: templates/faq.html:16 templates/tough/faq.html:14
+msgid ""
+"Most importanly - questions should be <strong>relevant</strong> to this "
+"community."
msgstr ""
+"Por encima de todo - las preguntas deben ser <strong>relevantes</strong>a "
+"esta comunidad."
-#: templates/footer.html:5
-msgid "About us"
+#: templates/faq.html:17 templates/tough/faq.html:15
+msgid ""
+"Before asking the question - please make sure to use search to see whether "
+"your question has alredy been answered."
msgstr ""
+"Antes de hacer tu pregunta - por favor usa el buscador para asegurarte que "
+"la pregunta no este ya hecha."
-#: templates/footer.html:6 templates/header.html:13 templates/index.html:83
-msgid "faq"
+#: templates/faq.html:20 templates/tough/faq.html:18
+msgid "What questions should I avoid asking?"
+msgstr "¿Qué preguntas debería evitar preguntar?"
+
+#: templates/faq.html:21 templates/tough/faq.html:19
+msgid ""
+"Please avoid asking questions that are not relevant to this community, too "
+"subjective and argumentative."
msgstr ""
+"Evita hacer preguntas que no son relevantes a la comunidad, demasiado "
+"subjetivas o argumentativas."
+
+#: templates/faq.html:24 templates/tough/faq.html:22
+msgid "What should I avoid in my answers?"
+msgstr "¿Que debo evitar en mis respuestas?"
-#: templates/footer.html:8
-msgid "Contact"
+#: templates/faq.html:25 templates/tough/faq.html:23
+msgid ""
+"is a Q&A site, not a discussion group. Therefore - please avoid having "
+"discussions in your answers, comment facility allows some space for brief "
+"discussions."
msgstr ""
+"es un sitio de Preguntas y Respuestas, no un grupo de discusión. Por ende, "
+"intenta evitar discusiones en tus respuestas. Los comentarios permiten "
+"realizar pequeñas discusiones."
-#: templates/footer.html:9
-msgid "Privacy"
+#: templates/faq.html:28 templates/tough/faq.html:26
+msgid "Who moderates this community?"
+msgstr "¿Quién modera esta comunidad?"
+
+#: templates/faq.html:29 templates/tough/faq.html:27
+msgid "The short answer is: <strong>you</strong>."
+msgstr "La respuesta corta es: <strong>tú</strong>"
+
+#: templates/faq.html:30 templates/tough/faq.html:28
+msgid "This website is moderated by the users."
+msgstr "Este sitio es moderado por los usuarios."
+
+#: templates/faq.html:31 templates/tough/faq.html:29
+msgid ""
+"The reputation system allows users earn the authorization to perform a "
+"variety of moderation tasks."
msgstr ""
+"El sistema de reputación permite a los usuarios adquirir autorización para "
+"realizar diversas tareas de moderación."
-#: templates/footer.html:10
-msgid "Feedback"
+#: templates/faq.html:34 templates/tough/faq.html:32
+msgid "How does reputation system work?"
+msgstr "¿Cómo funciona el sistema de reputación?"
+
+#: templates/faq.html:35 templates/tough/faq.html:33
+msgid ""
+"Anyone can ask questions and give answers, points are not necessary for that."
msgstr ""
+"Cualquier usuario puede hacer preguntas y dar respuestas, no es necesario "
+"tener reputación para ello."
-#: templates/header.html:8
-msgid "logout"
+#: templates/faq.html:36 templates/tough/faq.html:34
+msgid ""
+"As we've said before, users help running this site. Point system helps "
+"select users who can administer this community."
msgstr ""
+"Como dijimos antes, los usuarios ayudan a crear este sitio. El sistema de "
+"reputación permite seleccionar usuarios que pueden moderar esta comunidad."
-#: templates/header.html:10 templates/authopenid/signup.html:39
-msgid "login"
+#: templates/faq.html:37 templates/tough/faq.html:35
+msgid ""
+"Reputation points roughly measure how community trusts you. These points are "
+"given to you directly by other members of the community."
msgstr ""
+"Los puntos de reputación miden a groso modo que tan respetado eres en la "
+"comunidad. Los puntos son dados a ti directamente por otros miembros de la "
+"comunidad"
-#: templates/header.html:12 templates/index.html:82
-msgid "about"
+#: templates/faq.html:40 templates/tough/faq.html:38
+msgid ""
+"For example, if you ask an interesting question or give a helpful answer, "
+"your input will be upvoted and you will gain more trust in the community."
msgstr ""
+"Por ejemplo, si haces una pregunta interesante, o das una respuesta valiosa, "
+"tu entrada va a ser votada positivamente y tu ganarás confianza en la "
+"comunidad."
-#: templates/header.html:23
-msgid "back to home page"
+#: templates/faq.html:41 templates/tough/faq.html:39
+msgid ""
+"If on the other hand someone gives a misleading answer, the answer will be "
+"voted down and he/she loses some points."
+msgstr ""
+"Si por el contrario, alguien da una respuesta que no corresponde, la "
+"respuesta será votada negativamente y el usuario perderá puntos."
+
+#: templates/faq.html:42 templates/tough/faq.html:40
+msgid ""
+"Each vote in favor will generate <strong>10</strong> points, each vote "
+"against will subtract <strong>2</strong> points."
+msgstr ""
+"Cada voto a favor generará <strong>10</strong> puntos, cada voto negativo "
+"restará <strong>2</strong> puntos."
+
+#: templates/faq.html:43 templates/tough/faq.html:41
+msgid ""
+"Through the votes of other people you can accumulate a maximum of "
+"<strong>200</strong> points."
+msgstr ""
+"A través del voto de otras personas puedes acumular un máximo de "
+"<strong>200</strong> puntos."
+
+#: templates/faq.html:44
+msgid "After accumulating certain number of points, you can do more:"
+msgstr "Luego de haber acumulado cierta cantidad de puntos, puedes hacer más:"
+
+#: templates/faq.html:52 templates/user_votes.html:14
+#: templates/tough/faq.html:50
+msgid "upvote"
+msgstr "votar positivo"
+
+#: templates/faq.html:56 templates/tough/faq.html:54
+msgid "use tags"
+msgstr "etiquetas usadas"
+
+#: templates/faq.html:60 templates/tough/faq.html:58
+msgid "add comments"
+msgstr "agregar comentarios"
+
+#: templates/faq.html:64 templates/user_votes.html:16
+#: templates/tough/faq.html:62
+msgid "downvote"
+msgstr "votar negativo"
+
+#: templates/faq.html:71 templates/tough/faq.html:69
+msgid "retag questions"
+msgstr "re-etiquetar preguntas"
+
+#: templates/faq.html:75 templates/tough/faq.html:73
+msgid "edit community wiki questions"
+msgstr "editar preguntas de la wiki comunitaria"
+
+#: templates/faq.html:79 templates/tough/faq.html:77
+msgid "edit any answer"
+msgstr "editar cualquier pregunta"
+
+#: templates/faq.html:83 templates/tough/faq.html:81
+msgid "open any closed question"
+msgstr "abrir cualquier pregunta cerrada"
+
+#: templates/faq.html:87 templates/tough/faq.html:85
+msgid "delete any comment"
+msgstr "borrar cualquier comentario"
+
+#: templates/faq.html:91 templates/tough/faq.html:89
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr ""
+"borrar cualquier pregunta o respuesta y realizar otras tareas de "
+"administración."
+
+#: templates/faq.html:98
+msgid "To register, do I need to create new password?"
+msgstr "¿Para registrarme, debo crearme una cuenta?"
+
+#: templates/faq.html:99 templates/tough/faq.html:97
+msgid ""
+"No, you don't have to. You can login through any service that supports "
+"OpenID, e.g. Google, Yahoo, AOL, etc."
+msgstr ""
+"No tienes porqué. Puedes ingresar usando cualquiera de los servicios que "
+"soportan OpenID, ej. Google, Yahoo, AOL, MyOpenID, etc."
+
+#: templates/faq.html:100 templates/tough/faq.html:98
+msgid "Login now!"
+msgstr "Ingresa ahora!"
+
+#: templates/faq.html:103 templates/tough/faq.html:101
+msgid "Why other people can edit my questions/answers?"
+msgstr "¿Porqué otras personas pueden editar mis preguntas y respuestas?"
+
+#: templates/faq.html:104 templates/tough/faq.html:102
+msgid "Goal of this site is..."
+msgstr "El objetivo de este sitio es..."
+
+#: templates/faq.html:104 templates/tough/faq.html:102
+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 ""
+"Entonces, las preguntas y respuestas pueden ser editadas como wiki por "
+"usuarios con experiencia, y esto mejora la calidad general del conocimiento "
+"guardado."
-#: templates/header.html:29 templates/header.html.py:60
+#: templates/faq.html:105 templates/tough/faq.html:103
+msgid "If this approach is not for you, we respect your choice."
+msgstr ""
+"Si esta forma de funcionamiento no es de tu agrado, respetamos tu elección."
+
+#: templates/faq.html:107 templates/tough/faq.html:105
+msgid "Still have questions?"
+msgstr "¿Aún tienes preguntas?"
+
+#: templates/faq.html:108
+msgid "Please ask your question, help make our community better!"
+msgstr "Por favor haz tu pregunta, ¡ayudanos a mejorar nuestra comunidad!"
+
+#: templates/faq.html:108 templates/header.html:29 templates/header.html.py:60
+#: templates/tough/faq.html:106
msgid "questions"
+msgstr "preguntas"
+
+#: templates/faq.html:108 templates/index.html:121
+#: templates/tough/faq.html:106
+msgid "."
msgstr ""
+#: templates/footer.html:7 templates/header.html:12 templates/index.html:83
+msgid "about"
+msgstr "acerca de"
+
+#: templates/footer.html:8 templates/header.html:13 templates/index.html:84
+msgid "faq"
+msgstr "preguntas frecuentes"
+
+#: templates/footer.html:9
+msgid "blog"
+msgstr "blog"
+
+#: templates/footer.html:10
+msgid "contact us"
+msgstr "contactenos"
+
+#: templates/footer.html:11
+msgid "privacy policy"
+msgstr "código de privacidad"
+
+#: templates/footer.html:12
+msgid "give feedback"
+msgstr "envía comentarios"
+
+#: templates/footer.html:18
+msgid "current revision"
+msgstr "revisión actual"
+
+#: templates/header.html:8
+msgid "logout"
+msgstr "salir"
+
+#: templates/header.html:10 templates/authopenid/signup.html:39
+msgid "login"
+msgstr "entrar"
+
+#: templates/header.html:23
+msgid "back to home page"
+msgstr "volver al inicio"
+
#: templates/header.html:31 templates/header.html.py:62
msgid "users"
-msgstr ""
+msgstr "usuarios"
#: templates/header.html:32
msgid "books"
-msgstr ""
+msgstr "libros"
-#: templates/header.html:34 templates/index.html:120
+#: templates/header.html:34 templates/index.html:121
msgid "unanswered questions"
-msgstr ""
+msgstr "sin respuesta"
#: templates/header.html:38
msgid "my profile"
-msgstr ""
+msgstr "mi perfil"
#: templates/header.html:42
msgid "ask a question"
-msgstr ""
+msgstr "hacer una pregunta"
#: templates/header.html:57
msgid "search"
-msgstr ""
+msgstr "buscar"
#: templates/index.html:6
msgid "Home"
-msgstr ""
+msgstr "Inicio"
-#: templates/index.html:21
+#: templates/index.html:7
+msgid "meta site keywords, comma separated"
+msgstr "palabras claves"
+
+#: templates/index.html:21 templates/questions.html:7
msgid "Questions"
-msgstr ""
+msgstr "Preguntas"
#: templates/index.html:23
msgid "last updated questions"
-msgstr ""
+msgstr "ultimas preguntas actualizadas"
-#: templates/index.html:23 templates/unanswered.html:20
+#: templates/index.html:23 templates/questions.html:25
+#: templates/unanswered.html:20 templates/tough/unanswered.html:18
msgid "newest"
-msgstr ""
+msgstr "más nuevas"
-#: templates/index.html:24
+#: templates/index.html:24 templates/questions.html:27
msgid "hottest questions"
-msgstr ""
+msgstr "preguntas más calientes"
-#: templates/index.html:24
+#: templates/index.html:24 templates/questions.html:27
msgid "hottest"
-msgstr ""
+msgstr "más calientes"
-#: templates/index.html:25
+#: templates/index.html:25 templates/questions.html:28
msgid "most voted questions"
-msgstr ""
+msgstr "preguntas más votadas"
-#: templates/index.html:25
+#: templates/index.html:25 templates/questions.html:28
msgid "most voted"
-msgstr ""
+msgstr "más votadas"
#: templates/index.html:26
msgid "all questions"
-msgstr ""
+msgstr "todas las preguntas"
-#: templates/index.html:46 templates/unanswered.html:36
-#: templates/users_questions.html:35
+#: templates/index.html:46 templates/questions.html:45
+#: templates/unanswered.html:36 templates/users_questions.html:35
+#: templates/tough/unanswered.html:34
msgid "answers"
-msgstr ""
+msgstr "respuestas"
#: templates/index.html:68 templates/question.html:112
-#: templates/question.html.py:479 templates/tags.html:46
+#: templates/question.html.py:479 templates/questions.html:84
+#: templates/questions.html.py:149 templates/tags.html:47
#: templates/unanswered.html:75 templates/unanswered.html.py:109
-#: templates/users_questions.html:52
+#: templates/users_questions.html:52 templates/tough/unanswered.html:72
+#: templates/tough/unanswered.html:105
msgid "see questions tagged"
-msgstr ""
+msgstr "ver preguntas etiquetadas"
#: templates/index.html:79
msgid "welcome to website"
-msgstr ""
+msgstr "bienvenido a sitio"
-#: templates/index.html:88
+#: templates/index.html:81
+msgid "what is this website"
+msgstr "que es este sitio"
+
+#: templates/index.html:82
+msgid "what can one do on this website"
+msgstr "que puede uno hacer en este sitio"
+
+#: templates/index.html:89
msgid "Recent tags"
-msgstr ""
+msgstr "Etiquetas recientes"
-#: templates/index.html:93
+#: templates/index.html:94
#, python-format
msgid "see questions tagged '%(tagname)s'"
-msgstr ""
+msgstr "ver preguntas etiquetadas '%(tagname)s'"
-#: templates/index.html:96 templates/index.html.py:120
+#: templates/index.html:97 templates/index.html.py:121
msgid "popular tags"
-msgstr ""
+msgstr "etiquetas populares"
-#: templates/index.html:100
+#: templates/index.html:101
msgid "Recent awards"
-msgstr ""
+msgstr "Reconocimientos recientes"
-#: templates/index.html:106
+#: templates/index.html:107
msgid "given to"
-msgstr ""
+msgstr "dados a"
-#: templates/index.html:111
+#: templates/index.html:112
msgid "all awards"
-msgstr ""
+msgstr "todos los reconocimientos"
-#: templates/index.html:115
+#: templates/index.html:116
msgid "subscribe to last 30 questions by RSS"
-msgstr ""
+msgstr "suscribirse a las últimas 30 preguntas por RSS"
-#: templates/index.html:120
+#: templates/index.html:121
msgid "Still looking for more? See"
-msgstr ""
+msgstr "¿Aún sigues buscando más? Ver"
-#: templates/index.html:120
+#: templates/index.html:121
msgid "complete list of quesionts"
-msgstr ""
+msgstr "lista completa de preguntas"
-#: templates/index.html:120
+#: templates/index.html:121
msgid "or"
-msgstr ""
-
-#: templates/index.html:120
-msgid "."
-msgstr ""
+msgstr "ó"
-#: templates/index.html:120
+#: templates/index.html:121
msgid "Please help us answer"
-msgstr ""
+msgstr "Ayudanos a responder"
#: templates/logout.html:6 templates/logout.html.py:17
msgid "Logout"
-msgstr ""
+msgstr "Salir"
#: templates/logout.html:20
msgid ""
"As a registered user you can login with your OpenID, log out of the site or "
"permanently remove your account."
msgstr ""
+"Como usuario registrado puedes ingresar con tu OpenID, salir del sitio o "
+"eliminar de forma permanente tu cuenta."
#: templates/logout.html:21
msgid "Logout now"
-msgstr ""
+msgstr "Salir ahora"
-#: templates/pagesize.html:5
-msgid "Size per page:"
-msgstr ""
+#: templates/pagesize.html:6
+msgid "posts per page"
+msgstr "entradas por página"
-#: templates/paginator.html:5
-msgid "Previous"
-msgstr ""
+#: templates/paginator.html:6 templates/paginator.html.py:7
+msgid "previous"
+msgstr "previo"
+
+#: templates/paginator.html:20
+msgid "current page"
+msgstr "página actúal"
+
+#: templates/paginator.html:23 templates/paginator.html.py:30
+msgid "page number "
+msgstr "número de página"
+
+#: templates/paginator.html:23 templates/paginator.html.py:30
+msgid "number - make blank in english"
+msgstr " "
+
+#: templates/paginator.html:34
+msgid "next page"
+msgstr "próxima página"
#: templates/privacy.html:6 templates/privacy.html.py:11
msgid "Privacy policy"
-msgstr ""
+msgstr "Código de Privacidad"
#: templates/privacy.html:15
msgid "general message about privacy"
-msgstr ""
+msgstr "mensaje de privacidad"
#: templates/privacy.html:18
msgid "Site Visitors"
-msgstr ""
+msgstr "Visitantes del Sitio"
#: templates/privacy.html:20
msgid "what technical information is collected about visitors"
-msgstr ""
+msgstr "que información es recolectada sobre los usuarios"
#: templates/privacy.html:23
msgid "Personal Information"
-msgstr ""
+msgstr "Información Personal"
#: templates/privacy.html:25
msgid "details on personal information policies"
-msgstr ""
+msgstr "describir código de manejo de la información personal"
#: templates/privacy.html:28
msgid "Other Services"
-msgstr ""
+msgstr "Otros servicios"
#: templates/privacy.html:30
msgid "details on sharing data with third parties"
-msgstr ""
+msgstr "detalles sobre compartir información con terceros"
#: templates/privacy.html:35
msgid "cookie policy details"
-msgstr ""
+msgstr "uso de cookies"
#: templates/privacy.html:37
msgid "Policy Changes"
-msgstr ""
+msgstr "Cambios de Códigos"
#: templates/privacy.html:38
msgid "how privacy policies can be changed"
-msgstr ""
+msgstr "como pueden ser cambiados los códigos de privacidad"
#: templates/question.html:66 templates/question.html.py:78
msgid "i like this post (click again to cancel)"
-msgstr ""
+msgstr "Me gusta esta entrada (clickear devuelta para cancelar)"
#: templates/question.html:68 templates/question.html.py:80
#: templates/question.html:273
msgid "current number of votes"
-msgstr ""
+msgstr "número actual de votos"
#: templates/question.html:73 templates/question.html.py:84
msgid "i dont like this post (click again to cancel)"
-msgstr ""
+msgstr "No me gusta esta entrada (clickear devuelta para cancelar)"
#: templates/question.html:90
msgid "mark this question as favorite (click again to cancel)"
-msgstr ""
+msgstr "marcar esta pregunta como favorita (clickear devuelta para cancelar)"
#: templates/question.html:96
msgid "remove favorite mark from this question (click again to restore mark)"
msgstr ""
+"remover marca de favorito a esta pregunta (clickear devuelta para volver a "
+"marcar)"
#: templates/question.html:121 templates/question.html.py:304
#: templates/revisions_answer.html:53 templates/revisions_question.html:53
msgid "edit"
-msgstr ""
+msgstr "editar"
#: templates/question.html:125 templates/question.html.py:314
msgid "delete"
-msgstr ""
+msgstr "borrar"
#: templates/question.html:130
msgid "reopen"
-msgstr ""
+msgstr "re-abrir"
#: templates/question.html:135
msgid "close"
-msgstr ""
+msgstr "cerrar"
#: templates/question.html:141 templates/question.html.py:327
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:142 templates/question.html.py:328
msgid "flag offensive"
-msgstr ""
+msgstr "marcar como ofensivo"
#: templates/question.html:154 templates/question.html.py:337
#: templates/revisions_answer.html:65 templates/revisions_question.html:65
msgid "updated"
-msgstr ""
+msgstr "actualizado"
#: templates/question.html:203 templates/question.html.py:384
#: templates/revisions_answer.html:63 templates/revisions_question.html:63
msgid "asked"
-msgstr ""
+msgstr "preguntado"
#: templates/question.html:233 templates/question.html.py:411
msgid "comments"
-msgstr ""
+msgstr "comentarios"
#: templates/question.html:234 templates/question.html.py:412
msgid "add comment"
-msgstr ""
+msgstr "agregar comentario"
#: templates/question.html:247
#, python-format
@@ -1185,343 +1577,322 @@ 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:249
#, python-format
msgid "close date %(question.closed_at)s"
-msgstr ""
+msgstr "fecha de cerrada %(question.closed_at)s"
-#: templates/question.html:256 templates/questions.html:44
-#: templates/user_stats.html:28
+#: templates/question.html:256 templates/user_stats.html:28
msgid "Answers"
-msgstr ""
+msgstr "Respuestas"
#: templates/question.html:258
msgid "oldest answers will be shown first"
-msgstr ""
+msgstr "la respuesta mas vieja será mostrada primero"
#: templates/question.html:258
msgid "oldest answers"
-msgstr ""
+msgstr "pregunta más vieja"
#: templates/question.html:259
msgid "newest answers will be shown first"
-msgstr ""
+msgstr "preguntas más nuevas serán mostradas primero"
#: templates/question.html:259
msgid "newest answers"
-msgstr ""
+msgstr "más nuevas"
#: templates/question.html:260
msgid "most voted answers will be shown first"
-msgstr ""
+msgstr "las preguntas más votadas serán mostradas primero"
#: templates/question.html:260
msgid "popular answers"
-msgstr ""
+msgstr "respuestas populares serán mostradas primero"
#: templates/question.html:272
msgid "i like this answer (click again to cancel)"
-msgstr ""
+msgstr "me gusta esta respuesta (clickear devuelta para cancelar)"
#: templates/question.html:278
msgid "i dont like this answer (click again to cancel)"
-msgstr ""
+msgstr "no me gusta esta respuesta (clickear devuelta para cancelar)"
#: templates/question.html:284
msgid "mark this answer as favorite (click again to undo)"
-msgstr ""
+msgstr "marcar esta respuesta como favorita (clickear devuelta para deshacer)"
#: templates/question.html:289
msgid "the author of the question has selected this answer as correct"
-msgstr ""
+msgstr "el autor de esta pregunta ha seleccionado esta respuesta como correcta"
#: templates/question.html:311
msgid "undelete"
-msgstr ""
+msgstr "deshacer eliminar"
#: templates/question.html:321
msgid "answer permanent link"
-msgstr ""
+msgstr "enlace permanente a respuesta"
#: templates/question.html:322
msgid "permanent link"
-msgstr ""
+msgstr "enlace permanente"
#: templates/question.html:436
msgid "Your answer"
-msgstr ""
+msgstr "Tu respuesta"
#: templates/question.html:460
msgid "Answer the question"
-msgstr ""
+msgstr "Responde la pregunta"
#: templates/question.html:462
msgid "Login to answer"
-msgstr ""
+msgstr "Ingresa para responder"
#: templates/question.html:474
msgid "Question tags"
-msgstr ""
+msgstr "Etiquetas de la pregunta"
#: templates/question.html:484
msgid "question asked"
-msgstr ""
+msgstr "pregunta preguntada"
#: templates/question.html:484 templates/question.html.py:490
#: templates/user_info.html:51
msgid "ago"
-msgstr ""
+msgstr "atrás"
#: templates/question.html:487
msgid "question was seen"
-msgstr ""
+msgstr "la pregunta fue vista"
#: templates/question.html:487
msgid "times"
-msgstr ""
+msgstr "veces"
#: templates/question.html:490
msgid "last updated"
-msgstr ""
+msgstr "última vez actualizada"
#: templates/question.html:495
msgid "Related questions"
-msgstr ""
+msgstr "Preguntas relacionadas"
#: templates/question_edit.html:4 templates/question_edit.html.py:65
msgid "Edit question"
-msgstr ""
+msgstr "Editar pregunta"
#: templates/question_edit_tips.html:4
msgid "question tips"
-msgstr ""
+msgstr "sugerencias sobre pregunta"
#: templates/question_edit_tips.html:7
msgid "please ask a relevant question"
-msgstr ""
+msgstr "por favor hacer preguntas relevantes"
#: templates/question_edit_tips.html:10
msgid "please try provide enough details"
-msgstr ""
-
-#: templates/question_edit_tips.html:13
-msgid "be clear and concise"
-msgstr ""
-
-#: templates/question_edit_tips.html:16
-msgid "see frequently asked questions"
-msgstr ""
-
-#: templates/question_edit_tips.html:22
-msgid "Markdown tips"
-msgstr ""
-
-#: templates/question_edit_tips.html:25
-msgid "*italic* or __italic__"
-msgstr ""
-
-#: templates/question_edit_tips.html:28
-msgid "**bold** or __bold__"
-msgstr ""
+msgstr "intente proveer suficientes detalles"
-#: templates/question_edit_tips.html:31
-msgid "link"
-msgstr ""
-
-#: templates/question_edit_tips.html:31 templates/question_edit_tips.html:36
-msgid "text"
-msgstr ""
-
-#: templates/question_edit_tips.html:36
-msgid "image"
-msgstr ""
+#: templates/questions.html:23
+msgid "Found by tags"
+msgstr "Encontradas por etiqueta"
-#: templates/question_edit_tips.html:40
-msgid "numbered list:"
-msgstr ""
-
-#: templates/question_edit_tips.html:45
-msgid "basic HTML tags are also supported"
-msgstr ""
-
-#: templates/question_edit_tips.html:48
-msgid "learn more about Markdown"
-msgstr ""
-
-#: templates/questions.html:6
-msgid "Question list"
-msgstr ""
+#: templates/questions.html:23
+msgid "Found by title"
+msgstr "Encontradas por titulo"
-#: templates/questions.html:22
-msgid "Tagged questions"
-msgstr ""
-
-#: templates/questions.html:22
-msgid "Query result"
-msgstr ""
-
-#: templates/questions.html:22
+#: templates/questions.html:23
msgid "All questions"
-msgstr ""
+msgstr "Todas las preguntas"
-#: templates/questions.html:24
-msgid "New questions"
-msgstr ""
-
-#: templates/questions.html:24
-msgid "Newest"
-msgstr ""
-
-#: templates/questions.html:25
-msgid "Newest updated questions"
-msgstr ""
-
-#: templates/questions.html:25
-msgid "Active"
-msgstr ""
+#: templates/questions.html:25 templates/unanswered.html:20
+#: templates/tough/unanswered.html:18
+msgid "most recently asked questions"
+msgstr "preguntas hechas más recientemente"
#: templates/questions.html:26
-msgid "Questions with most answers"
-msgstr ""
+msgid "most recently updated questions"
+msgstr "preguntas actualizadas más recientemente"
#: templates/questions.html:26
-msgid "Hottest"
-msgstr ""
-
-#: templates/questions.html:27
-msgid "Questions with most votes"
-msgstr ""
-
-#: templates/questions.html:27
-msgid "Best"
-msgstr ""
+msgid "active"
+msgstr "actividad"
-#: templates/questions.html:45
-msgid "Votes"
-msgstr ""
-
-#: templates/questions.html:46
-msgid "Visits"
-msgstr ""
-
-#: templates/questions.html:57 templates/questions.html.py:69
-msgid "Community wiki"
-msgstr ""
-
-#: templates/questions.html:83
-msgid "Browse questions with tag of "
-msgstr ""
-
-#: templates/questions.html:125 templates/unanswered.html:105
+#: templates/questions.html:109
+#, fuzzy, python-format
+msgid ""
+"\n"
+"\t\t\thave total %(q_num)s question tagged %(tagname)s\n"
+"\t\t\t"
+msgid_plural ""
+"\n"
+"\t\t\thave total %(q_num)s questions tagged %(tagname)s\n"
+"\t\t\t"
+msgstr[0] "ver preguntas etiquetadas '%(tagname)s'"
+msgstr[1] "ver pregunta etiquetada '%(tagname)s'"
+
+#: templates/questions.html:116
+#, python-format
+msgid ""
+"\n"
+"\t\t\thave total %(q_num)s question containing %(searchtitle)s\n"
+"\t\t\t"
+msgid_plural ""
+"\n"
+"\t\t\thave total %(q_num)s questions containing %(searchtitle)s\n"
+"\t\t\t"
+msgstr[0] ""
+"\n"
+"\t\t\thay un total de %(q_num)s preguntas que contienen %(searchtitle)s\n"
+"\t\t\t"
+msgstr[1] ""
+"\n"
+"\t\t\thay un total de %(q_num)s pregunta que contiene %(searchtitle)s\n"
+"\t\t\t"
+
+#: templates/questions.html:124
+msgid "latest questions info"
+msgstr "<strong>Más recientes</strong> preguntas son mostradas primero."
+
+#: templates/questions.html:128
+msgid "Questions are sorted by the <strong>time of last update</strong>."
+msgstr ""
+"Las preguntas estan ordenadas por <strong>fecha de último update</strong>."
+
+#: templates/questions.html:129
+msgid "Most recently answered ones are shown first."
+msgstr "Las más recientemente respondidas son mostradas primero."
+
+#: templates/questions.html:133
+msgid "Questions sorted by <strong>number of responses</strong>."
+msgstr "Preguntas ordenadas por <strong>número de respuestas</strong>."
+
+#: templates/questions.html:134
+msgid "Most answered questions are shown first."
+msgstr "Preguntas más respondidas aparecen primero."
+
+#: templates/questions.html:138
+msgid "Questions are sorted by the <strong>number of votes</strong>."
+msgstr "Las preguntas son ordenadas por el <strong>número de votos</strong>."
+
+#: templates/questions.html:139
+msgid "Most voted questions are shown first."
+msgstr "Las preguntas más votadas son mostradas primero."
+
+#: templates/questions.html:146 templates/unanswered.html:105
+#: templates/tough/unanswered.html:101
msgid "Related tags"
-msgstr ""
+msgstr "Etiquetas relacionadas"
#: templates/reopen.html:6 templates/reopen.html.py:16
msgid "Reopen question"
-msgstr ""
+msgstr "Re-abrir pregunta"
#: templates/reopen.html:19
msgid "Open the previously closed question"
-msgstr ""
+msgstr "Abrir pregunta previamente cerrada"
#: templates/reopen.html:22
msgid "The question was closed for the following reason "
-msgstr ""
+msgstr "La pregunta fue cerrada por el siguiente motivo "
#: templates/reopen.html:22
msgid "reason - leave blank in english"
-msgstr ""
+msgstr "razón - "
#: templates/reopen.html:22
msgid "on "
-msgstr ""
+msgstr "el "
#: templates/reopen.html:22
msgid "date closed"
-msgstr ""
+msgstr "fecha cerrada"
#: templates/reopen.html:29
msgid "Reopen this question"
-msgstr ""
+msgstr "Re-abrir esta pregunta"
#: templates/revisions_answer.html:7 templates/revisions_answer.html.py:36
#: templates/revisions_question.html:8 templates/revisions_question.html:36
msgid "Revision history"
-msgstr ""
+msgstr "Historial de revisiones"
-#: templates/tags.html:5 templates/tags.html.py:28
+#: templates/tags.html:6 templates/tags.html.py:29
msgid "Tag list"
-msgstr ""
+msgstr "Lista de etiquetas"
-#: templates/tags.html:30
+#: templates/tags.html:31
msgid "sorted alphabetically"
-msgstr ""
+msgstr "ordenar alfabéticamente"
-#: templates/tags.html:30
+#: templates/tags.html:31
msgid "by name"
-msgstr ""
+msgstr "por nombre"
-#: templates/tags.html:31
+#: templates/tags.html:32
msgid "sorted by frequency of tag use"
-msgstr ""
+msgstr "ordenar por frecuencia de uso de la etiqueta"
-#: templates/tags.html:31
+#: templates/tags.html:32
msgid "by popularity"
-msgstr ""
+msgstr "por popularidad"
-#: templates/tags.html:37
+#: templates/tags.html:38
msgid "All tags matching query"
-msgstr ""
+msgstr "Todas las etiquetas que coincidan con la busqueda"
-#: templates/tags.html:37
+#: templates/tags.html:38
msgid "all tags - make this empty in english"
-msgstr ""
+msgstr "todas las tags"
-#: templates/tags.html:40
+#: templates/tags.html:41
msgid "Nothing found"
-msgstr ""
+msgstr "Nada encontrado"
#: templates/unanswered.html:7 templates/unanswered.html.py:18
+#: templates/tough/unanswered.html:5 templates/tough/unanswered.html.py:16
msgid "Unanswered questions"
-msgstr ""
-
-#: templates/unanswered.html:20
-msgid "most recently asked questions"
-msgstr ""
+msgstr "Preguntas sin respuesta"
#: templates/unanswered.html:97
#, python-format
msgid "have %(num_q)s unanswered questions"
msgstr ""
+"<div class=\"questions-count\">%(num_q)s</div> preguntas <strong>sin "
+"respuesta</strong> "
#: templates/unanswered.html:99
msgid "Have a total of"
-msgstr ""
+msgstr "Hay un total de"
#: templates/user_edit.html:6
msgid "Edit user profile"
-msgstr ""
+msgstr "Editar perfil de usuario"
#: templates/user_edit.html:19
msgid "edit profile"
-msgstr ""
+msgstr "editar perfil"
#: templates/user_edit.html:31
msgid "image associated with your email address"
-msgstr ""
+msgstr "imagen asociada con tu email"
#: templates/user_edit.html:31
msgid "avatar"
-msgstr ""
+msgstr "avatar"
#: templates/user_edit.html:36 templates/user_info.html:31
msgid "Registered user"
-msgstr ""
+msgstr "Usuario registrado"
#: templates/user_edit.html:82
msgid "Update"
-msgstr ""
+msgstr "Actualización"
#: templates/user_info.html:34
msgid "update profile"
@@ -1529,143 +1900,136 @@ msgstr ""
#: templates/user_info.html:40
msgid "real name"
-msgstr ""
+msgstr "nombre real"
#: templates/user_info.html:45
msgid "member for"
-msgstr ""
+msgstr "miembro de"
#: templates/user_info.html:50
msgid "last seen"
-msgstr ""
+msgstr "última vez visto"
#: templates/user_info.html:56
msgid "user website"
-msgstr ""
+msgstr "sitio web del usuario"
#: templates/user_info.html:62
msgid "location"
-msgstr ""
+msgstr "ubicación"
#: templates/user_info.html:69
msgid "age"
-msgstr ""
+msgstr "edad"
#: templates/user_info.html:70
msgid "age unit"
-msgstr ""
+msgstr "unidad de edad"
#: templates/user_info.html:75
msgid "todays unused votes"
-msgstr ""
+msgstr "votos de hoy no usados"
#: templates/user_info.html:76
msgid "votes left"
-msgstr ""
+msgstr "votos restantes"
#: templates/user_stats.html:15
msgid "User questions"
-msgstr ""
+msgstr "Preguntas del usuario"
#: templates/user_stats.html:37
#, python-format
msgid "the answer has been voted for %(vote_count)s times"
-msgstr ""
+msgstr "la respuesta ha sido votada %(vote_count)s veces"
#: templates/user_stats.html:37
msgid "this answer has been selected as correct"
-msgstr ""
+msgstr "esta respuesta ha sido seleccionada como correcta"
#: templates/user_stats.html:43
#, python-format
msgid "the answer has been commented %(answered_question.comment_count)s times"
msgstr ""
+"la respuesta ha sido comentada %(answered_question.comment_count)s veces"
#: templates/user_stats.html:56
msgid "votes total"
-msgstr ""
+msgstr "votos totales"
#: templates/user_stats.html:65
msgid "user has voted up this many times"
-msgstr ""
+msgstr "el usuario ha votado positivo esta cantidad de veces"
#: templates/user_stats.html:70
msgid "user voted down this many times"
-msgstr ""
+msgstr "el usuario voto negativo esta cantidad de veces"
#: templates/user_stats.html:84
msgid "Tags"
-msgstr ""
+msgstr "Etiquetas"
#: templates/user_stats.html:94
#, python-format
msgid "see other questions tagged '%(tag)s' "
-msgstr ""
+msgstr "ver otras preguntas etiqueteadas '%(tag)s'"
#: templates/user_tabs.html:7
msgid "User profile"
-msgstr ""
+msgstr "Perfil de usuario"
#: templates/user_tabs.html:16
msgid "graph of user reputation"
-msgstr ""
+msgstr "gráfica de la reputación del usuario"
#: templates/user_tabs.html:17
msgid "reputation history"
-msgstr ""
+msgstr "historial de reputación"
#: templates/user_tabs.html:24
msgid "favorites"
-msgstr ""
+msgstr "favoritos"
#: templates/user_tabs.html:29
msgid "settings"
-msgstr ""
+msgstr "preferencias"
-#: templates/user_votes.html:14
-msgid "upvote"
-msgstr ""
-
-#: templates/user_votes.html:16
-msgid "downvote"
-msgstr ""
-
-#: templates/users.html:5 templates/users.html.py:23
+#: templates/users.html:6 templates/users.html.py:24
msgid "Users"
-msgstr ""
+msgstr "Usuarios"
-#: templates/users.html:26
+#: templates/users.html:27
msgid "recent"
-msgstr ""
+msgstr "reciente"
-#: templates/users.html:27
+#: templates/users.html:28
msgid "oldest"
-msgstr ""
+msgstr "más viejo"
-#: templates/users.html:28
+#: templates/users.html:29
msgid "by username"
-msgstr ""
+msgstr "por nombre de usuario"
-#: templates/users.html:34
+#: templates/users.html:35
#, python-format
msgid "users matching query %(suser)s:"
-msgstr ""
+msgstr "usuarios que coincidan con la busqueda %(suser)s:"
-#: templates/users.html:38
+#: templates/users.html:39
msgid "Nothing found."
-msgstr ""
+msgstr "Nada encontrado."
#: templates/users_questions.html:11
msgid "this questions was selected as favorite"
-msgstr ""
+msgstr "esta pregunta ha sido seleccionada como favorita"
#: templates/users_questions.html:33
msgid "this answer has been accepted to be correct"
-msgstr ""
+msgstr "esta respuesta ha sido aceptada como correcta"
#: templates/authopenid/changeemail.html:6
msgid "Account: change email"
-msgstr ""
+msgstr "Cuenta: cambiar el email"
#: templates/authopenid/changeemail.html:9
msgid ""
@@ -1673,301 +2037,370 @@ msgid ""
"Please keep this email address up to date so we can send you a password-"
"reset email if you request one."
msgstr ""
+"Aquí es donde puedes cambiar el email asociado a tu cuenta de usuario.Por "
+"favor manten esta dirección de correo al día de forma que podamos mandarte "
+"un cambio de contraseña si tu así lo requieres."
#: templates/authopenid/changeemail.html:11
#: templates/authopenid/changeopenid.html:13
#: templates/authopenid/changepw.html:18 templates/authopenid/delete.html:14
#: templates/authopenid/delete.html:24
msgid "Please correct errors below:"
-msgstr ""
+msgstr "Por favor corrija los errores debajo: "
#: templates/authopenid/changeemail.html:28
msgid "Email"
-msgstr ""
+msgstr "Email"
#: templates/authopenid/changeemail.html:29
#: templates/authopenid/signin.html:60
msgid "Password"
-msgstr ""
+msgstr "Contraseña"
#: templates/authopenid/changeemail.html:31
msgid "Change email"
-msgstr ""
+msgstr "Cambiar dirección email"
#: templates/authopenid/changeopenid.html:7
msgid "Account: change OpenID URL"
-msgstr ""
+msgstr "Cuenta: cambiar la URL de OpenID"
#: templates/authopenid/changeopenid.html:11
msgid ""
"This is where you can change your OpenID URL. Make sure you remember it!"
-msgstr ""
+msgstr "Aquí es donde puedes cambiar tu OpenID URL. Asegurate de recordarla!"
#: templates/authopenid/changeopenid.html:28
msgid "OpenID URL:"
-msgstr ""
+msgstr "URL de OpenID:"
#: templates/authopenid/changeopenid.html:29
msgid "Change OpenID"
-msgstr ""
+msgstr "Cambiar OpenID"
#: templates/authopenid/changepw.html:13
msgid "Account: change password"
-msgstr ""
+msgstr "Cuenta: cambiar contraseña"
#: templates/authopenid/changepw.html:16
msgid "This is where you can change your password. Make sure you remember it!"
-msgstr ""
+msgstr "Aquí es donde puedes cambiar tu contraseña. Asegurate de recordarlo!"
#: templates/authopenid/changepw.html:26
msgid "Current password"
-msgstr ""
+msgstr "Contraseña actual"
#: templates/authopenid/changepw.html:27
msgid "New password"
-msgstr ""
+msgstr "Nueva contraseña"
#: templates/authopenid/changepw.html:28
msgid "New password again"
-msgstr ""
+msgstr "Nueva contraseña nuevamente"
#: templates/authopenid/changepw.html:29 templates/authopenid/settings.html:28
msgid "Change password"
-msgstr ""
+msgstr "Cambiar contraseña"
#: templates/authopenid/complete.html:4
msgid "Connect your OpenID with this site"
-msgstr ""
+msgstr "Vincular tu OpenID con este sitio"
#: templates/authopenid/complete.html:7
msgid "Connect your OpenID with your account on this site"
-msgstr ""
+msgstr "Vincular tu OpenID con tu cuenta en este sitio"
#: templates/authopenid/complete.html:10
msgid "Your OpenID is accepted. Please complete this to finish registration."
msgstr ""
+"Tu OpenID es aceptada. Por favor completa lo siguiente para finalizar el "
+"registro."
#: templates/authopenid/complete.html:11
msgid "This account already exists, please use another."
-msgstr ""
+msgstr "Esta cuenta ya existe, por favor usar otra."
#: templates/authopenid/complete.html:16 templates/authopenid/complete.html:29
#: templates/authopenid/signin.html:43
msgid "Sorry, looks like we have some errors:"
-msgstr ""
+msgstr "Ups, parece que hay errores:"
#: templates/authopenid/complete.html:45
msgid "New account"
-msgstr ""
+msgstr "Nueva cuenta"
#: templates/authopenid/complete.html:46
msgid "User name (<i>will be shown to others, cannot be modified</i>)"
msgstr ""
+"Nombre de usuario (<i>será mostrado a otros, no puede ser modificado</i>)"
#: templates/authopenid/complete.html:47
msgid "Email (<i>not shared with anyone</i>)"
-msgstr ""
+msgstr "Email (<i>no será compartido con nadie</i>)"
#: templates/authopenid/complete.html:48
msgid "create account"
-msgstr ""
+msgstr "crear cuenta"
#: templates/authopenid/complete.html:56
msgid "Existing account"
-msgstr ""
+msgstr "Cuenta existente"
#: templates/authopenid/complete.html:57
msgid "user name"
-msgstr ""
+msgstr "nombre de usuario"
#: templates/authopenid/complete.html:58
msgid "password"
-msgstr ""
+msgstr "contraseña"
#: templates/authopenid/complete.html:61
msgid "Register"
-msgstr ""
+msgstr "Registrarse"
#: templates/authopenid/complete.html:62 templates/authopenid/signin.html:62
msgid "Forgot your password?"
-msgstr ""
+msgstr "¿Olvidaste tu contraseña?"
#: templates/authopenid/delete.html:8
msgid "Account: delete account"
-msgstr ""
+msgstr "Cuenta: borrar cuenta"
#: templates/authopenid/delete.html:12
msgid ""
"Note: After deleting your account, anyone will be able to register this "
"username."
msgstr ""
+"Nota: Luego de borrar tu cuenta, cualquiera podrá registrarse con este "
+"nombre de usuario."
#: templates/authopenid/delete.html:16
msgid "Check confirm box, if you want delete your account."
-msgstr ""
+msgstr "Marca caja de confirmación, si deseas borrar tu cuenta."
#: templates/authopenid/delete.html:19
msgid "Password:"
-msgstr ""
+msgstr "Contraseña"
#: templates/authopenid/delete.html:31
msgid "I am sure I want to delete my account."
-msgstr ""
+msgstr "Estoy seguro que quiero borrar mi cuenta."
#: templates/authopenid/delete.html:32
msgid "Password/OpenID URL"
-msgstr ""
+msgstr "Contraseña/OpenID URL"
#: templates/authopenid/delete.html:32
msgid "(required for your security)"
-msgstr ""
+msgstr "(requerido por tu seguridad)"
#: templates/authopenid/delete.html:34
msgid "Delete account permanently"
-msgstr ""
+msgstr "Borrar la cuenta de forma permanente"
#: templates/authopenid/sendpw.html:3 templates/authopenid/sendpw.html.py:7
msgid "Send new password"
-msgstr ""
+msgstr "Enviar nueva contraseña"
#: templates/authopenid/sendpw.html:11
msgid "Lost your password? No problem - here you can reset it."
-msgstr ""
+msgstr "¿Haz perdido tu contraseña? No hay problema - aquí puedes re-crearla."
#: templates/authopenid/sendpw.html:12
msgid ""
"Please enter your username below and new password will be sent to your "
"registered e-mail"
msgstr ""
+"Por favor, ingresa tu nombre de usuario y una nueva contraseña será enviada "
+"a la dirección de email registrada."
#: templates/authopenid/sendpw.html:29
msgid "Reset password"
-msgstr ""
+msgstr "Re-crear contraseña"
#: templates/authopenid/sendpw.html:29
msgid "return to login"
-msgstr ""
+msgstr "volver a 'Ingresar'"
#: templates/authopenid/sendpw.html:32
msgid ""
"Note: your new password will be activated only after you click the "
"activation link in the email message"
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/settings.html:29
msgid "Give your account a new password."
-msgstr ""
+msgstr "Crea una nueva contraseña para tu cuenta."
#: templates/authopenid/settings.html:30
msgid "Change email "
-msgstr ""
+msgstr "Cambiar email "
#: templates/authopenid/settings.html:31
msgid "Add or update the email address associated with your account."
-msgstr ""
+msgstr "Agrega o actualiza el email asociado a tu cuenta."
#: templates/authopenid/settings.html:34
msgid "Change openid associated to your account"
-msgstr ""
+msgstr "Cambia el OpenID asociado a tu cuenta"
#: templates/authopenid/settings.html:37
msgid "Delete account"
-msgstr ""
+msgstr "Eliminar cuenta"
#: templates/authopenid/settings.html:38
msgid "Erase your username and all your data from website"
-msgstr ""
+msgstr "Eliminar tu nombre de usuario y toda tu información del sitio"
#: templates/authopenid/signin.html:3 templates/authopenid/signin.html:16
msgid "User login"
-msgstr ""
+msgstr "Ingreso de usuario"
#: templates/authopenid/signin.html:21
msgid "we support two login modes"
msgstr ""
+"Puedes ingresar por cualquiera de los siguientes servicios, o "
+"tradicionalmente- usando nombre de usuario y contraseña locales"
#: templates/authopenid/signin.html:26 templates/authopenid/signup.html:49
msgid "Login with your OpenID"
-msgstr ""
+msgstr "Ingresar con tu OpenID"
#: templates/authopenid/signin.html:28
msgid "select openid provider"
-msgstr ""
+msgstr "1) Selecciona tu proveedor de OpenID"
#: templates/authopenid/signin.html:32
msgid "verify openid link and login"
msgstr ""
+"2) Varifica la URL de tu OpenID (escribe tu nombre de usuario donde dice "
+"{nombre de usuario} si lo ves) y luego clickea 'ingresar'"
#: templates/authopenid/signin.html:58
msgid "Use login name and password"
-msgstr ""
+msgstr "Nombre de usuario y contraseña"
#: templates/authopenid/signin.html:59
msgid "Login name"
-msgstr ""
+msgstr "Nombre de usuario"
#: templates/authopenid/signin.html:63
msgid "Create new acccount"
-msgstr ""
+msgstr "Crear cuenta nueva"
#: templates/authopenid/signin.html:72
msgid "Why use OpenID?"
-msgstr ""
+msgstr "¿Porqué usar OpenID?"
#: templates/authopenid/signin.html:76
msgid "with openid it is easier"
-msgstr ""
+msgstr "Con OpenID no necesitas crear un nuevo nombre de usuario y contraseña."
#: templates/authopenid/signin.html:79
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:82
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:85
msgid "openid is supported open standard"
msgstr ""
+"OpenID es basado en un standard abierto, apoyado por muchas organizaciones."
#: templates/authopenid/signin.html:89
msgid "Find out more"
-msgstr ""
+msgstr "Averigua más"
#: templates/authopenid/signin.html:90
msgid "Get OpenID"
-msgstr ""
+msgstr "Adquiere una OpenID"
#: templates/authopenid/signup.html:2 templates/authopenid/signup.html.py:6
msgid "Signup"
-msgstr ""
+msgstr "Registrate"
#: templates/authopenid/signup.html:10
msgid ""
"We support two types of user registration: conventional username/password, "
"and"
msgstr ""
+"Soportamos dos formas de registro de usuario: convencional usuario/"
+"contraseña, y"
#: templates/authopenid/signup.html:10
msgid "the OpenID method"
-msgstr ""
+msgstr "OpenID"
#: templates/authopenid/signup.html:15
msgid "Sorry, looks like we have some errors"
-msgstr ""
+msgstr "Ups, parece que hay errores."
#: templates/authopenid/signup.html:33
msgid "Conventional registration"
-msgstr ""
+msgstr "Registro clásico"
#: templates/authopenid/signup.html:34
msgid "choose a user name"
-msgstr ""
+msgstr "elije un nombre de usuario"
#: templates/authopenid/signup.html:40
msgid "back to login"
-msgstr ""
+msgstr "volver al ingreso de usuario"
#: templates/authopenid/signup.html:46
msgid "Register with your OpenID"
+msgstr "Registrate con tu OpenID"
+
+#: templates/tough/question_retag.html:2
+msgid "Revise tags"
+msgstr "Revisar etiquetas"
+
+#: templates/tough/question_retag.html:37
+msgid "tags are requried"
+msgstr "las etiquetas son requeridas"
+
+#: templates/tough/question_retag.html:38
+msgid "up to 5 tags, less than 20 characters each"
+msgstr "hasta 5 etiquetas, menos de 20 caracteres cada una"
+
+#: templates/tough/question_retag.html:51
+msgid "Change tags"
+msgstr "Cambiar etiquetas"
+
+#: templates/tough/question_retag.html:74
+msgid "Change now"
+msgstr "Cambiar ahora"
+
+#: templates/tough/question_retag.html:85
+msgid "Why use and modify tags?"
+msgstr "¿Porqué usar y modificar etiquetas?"
+
+#: templates/tough/question_retag.html:96
+msgid "tag editors receive special awards from the community"
msgstr ""
+"los editores de etiquetas reciben distinciones especiales de la comunidad"
+
+#: templates/tough/unanswered.html:95
+msgid "number of <strong>unanswered</strong> questions"
+msgstr "número de respuestas <strong>sin responder</strong>"
+
+#~ msgid "Community gives you awards for your questions, answers and votes."
+#~ msgstr ""
+#~ "La comunidad te da distinciones por tus preguntas, respuestas y votos."
+
+#
+#~ msgid "editing tips"
+#~ msgstr "Tips"
+
+#~ msgid "Newest questions shown first."
+#~ msgstr ""
+#~ "Questions are sorted by <strong>entry date</strong>.Newest questions "
+#~ "shown first."
diff --git a/locale/zh_CN/LC_MESSAGES/django.mo b/locale/zh_CN/LC_MESSAGES/django.mo
deleted file mode 100644
index 3d45237b..00000000
--- a/locale/zh_CN/LC_MESSAGES/django.mo
+++ /dev/null
Binary files differ
diff --git a/locale/zh_CN/LC_MESSAGES/django.po b/locale/zh_CN/LC_MESSAGES/django.po
index ba32e84a..206f4b6f 100644
--- a/locale/zh_CN/LC_MESSAGES/django.po
+++ b/locale/zh_CN/LC_MESSAGES/django.po
@@ -1,5 +1,3 @@
-# author Evgeny Fadeev (evgeny.fadeev@gmail.com)
-# site-specific messages
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
@@ -66,7 +64,6 @@ msgid "this name is already in use - please try anoter"
msgstr "该用户名已被注册,请换一个试试"
#: django_authopenid/forms.py:184
-#, fuzzy
msgid ""
"This email is already registered in our database. Please "
"choose another."
@@ -78,7 +75,6 @@ msgid ""
msgstr ""
#: django_authopenid/forms.py:253
-#, fuzzy
msgid "choose a username"
msgstr "选择一个用户名"
@@ -105,7 +101,6 @@ msgid "new passwords do not match"
msgstr ""
#: django_authopenid/forms.py:434
-#, fuzzy
msgid "Incorrect username."
msgstr "选择一个用户名"
@@ -132,7 +127,6 @@ msgid "sendpw/"
msgstr ""
#: django_authopenid/urls.py:26
-#, fuzzy
msgid "delete/"
msgstr "删除"
@@ -1020,6 +1014,8 @@ msgid "most voted questions"
msgstr "投票次数最多的问题"
#: templates/index.html:25
+#"最有价值问题"
+#"最新问题"
msgid "most voted"
msgstr "最有价值的问题"
@@ -1041,7 +1037,6 @@ msgid "see questions tagged"
msgstr "查看有关"
#: templates/index.html:79
-#, fuzzy
msgid "welcome to website"
msgstr "CNProg欢迎您!"
@@ -1053,7 +1048,7 @@ msgstr "最新标签"
#: templates/index.html:93
#, fuzzy, python-format
msgid "see questions tagged '%(tagname)s'"
-msgstr "查看有关'%s'的问题"
+msgstr "查看有关'%(tagname)s'的问题"
#: templates/index.html:96 templates/index.html.py:120
msgid "popular tags"
@@ -1092,6 +1087,30 @@ msgstr "或者"
msgid "."
msgstr "。"
+#: templates/pagesize.html:5
+msgid "posts per page"
+msgstr "每页显示:"
+
+#: templates/paginator.html:5
+msgid "previous"
+msgstr "上一页"
+
+#: templates/questions.html:22
+msgid "Found by tags"
+msgstr "标签问题"
+
+#: templates/questions.html:25
+msgid "Active"
+msgstr "活跃问题"
+
+#: templates/questions.html:125
+msgid "Related tags"
+msgstr "相关标签"
+
+#: templates/authopenid/changeemail.html:10
+msgid "Account: change email"
+msgstr "修改电子邮件"
+
#: templates/index.html:120
msgid "Please help us answer"
msgstr "请帮助我们回答"
@@ -1117,12 +1136,6 @@ msgstr "点击退出登录"
msgid "Size per page:"
msgstr "每页显示"
-# paginator.html
-#: templates/paginator.html:5
-#, fuzzy
-msgid "Previous"
-msgstr "上一页"
-
#: templates/privacy.html:6 templates/privacy.html.py:11
msgid "Privacy policy"
msgstr "隐私政策"
@@ -1432,39 +1445,10 @@ msgstr "基本的HTML标签也是支持的"
msgid "learn more about Markdown"
msgstr "有关Markdown详细说明"
-#: templates/questions.html:6
-#, fuzzy
-msgid "Question list"
-msgstr "问题列表"
-
-#: templates/questions.html:22
-#, fuzzy
-msgid "Tagged questions"
-msgstr "相似的问题"
-
-#: templates/questions.html:22
-msgid "Query result"
-msgstr ""
-
#: templates/questions.html:22
msgid "All questions"
msgstr "所有问题"
-#: templates/questions.html:24
-#, fuzzy
-msgid "New questions"
-msgstr "问题"
-
-#: templates/questions.html:24
-#, fuzzy
-msgid "Newest"
-msgstr "最新问题"
-
-#: templates/questions.html:25
-#, fuzzy
-msgid "Newest updated questions"
-msgstr "最新更新的问题"
-
#: templates/questions.html:25
#, fuzzy
msgid "Active"
@@ -1475,30 +1459,10 @@ msgstr "活跃问题"
msgid "Questions with most answers"
msgstr "您正在浏览的问题含有以下标签"
-#: templates/questions.html:26
-#, fuzzy
-msgid "Hottest"
-msgstr "热门问题"
-
#: templates/questions.html:27
msgid "Questions with most votes"
msgstr ""
-#: templates/questions.html:27
-#, fuzzy
-msgid "Best"
-msgstr "最新问题"
-
-#: templates/questions.html:45
-#, fuzzy
-msgid "Votes"
-msgstr "票"
-
-#: templates/questions.html:46
-#, fuzzy
-msgid "Visits"
-msgstr "网站访问者"
-
# index.html
#: templates/questions.html:57 templates/questions.html.py:69
#, fuzzy
@@ -2102,350 +2066,350 @@ msgstr "返回登录"
msgid "Register with your OpenID"
msgstr "使用OpenID注册"
-#~ msgid "meta site keywords, comma separated"
-#~ msgstr ""
-#~ "技术问答社区,中国程序员,编程技术社区,程序员社区,程序员论坛,程序员"
-#~ "wiki,程序员博客"
+msgid "meta site keywords, comma separated"
+msgstr ""
+"技术问答社区,中国程序员,编程技术社区,程序员社区,程序员论坛,程序员"
+"wiki,程序员博客"
-#~ msgid "what is this website"
-#~ msgstr ""
-#~ "CNProg是一个<strong>面向程序员</strong>的可协作编辑的<strong>开放源代码问"
-#~ "答社区</strong>。"
+msgid "what is this website"
+msgstr ""
+"CNProg是一个<strong>面向程序员</strong>的可协作编辑的<strong>开放源代码问"
+"答社区</strong>。"
-#~ msgid "what can one do on this website"
-#~ msgstr ""
-#~ "您可以在这里提问各类<strong>程序技术问题</strong> - 问题不分语言和平台。 "
-#~ "同时也希望您对力所能及的问题,给予您的宝贵答案。"
+msgid "what can one do on this website"
+msgstr ""
+"您可以在这里提问各类<strong>程序技术问题</strong> - 问题不分语言和平台。 "
+"同时也希望您对力所能及的问题,给予您的宝贵答案。"
-#~ msgid "Goal of this site is..."
-#~ msgstr "CNProg 是为了帮助程序员解决更多问题,更加方便的解决问题。"
+msgid "Goal of this site is..."
+msgstr "CNProg 是为了帮助程序员解决更多问题,更加方便的解决问题。"
-#~ msgid "Community gives you awards for your questions, answers and votes."
-#~ msgstr ""
-#~ "提出问题,给予回答,投出你的票 - CNProg 会针对你在社区的表现,授予你各类奖"
-#~ "牌。"
+msgid "Community gives you awards for your questions, answers and votes."
+msgstr ""
+"提出问题,给予回答,投出你的票 - CNProg 会针对你在社区的表现,授予你各类奖"
+"牌。"
-#~ msgid "please make your answer relevant to this community"
-#~ msgstr "您的问题与编程相关吗?"
+msgid "please make your answer relevant to this community"
+msgstr "您的问题与编程相关吗?"
-#~ msgid "book technical Q&A"
-#~ msgstr "图书相关的技术答疑"
+msgid "book technical Q&A"
+msgstr "图书相关的技术答疑"
-#~ msgid "blog"
-#~ msgstr "Blog"
+msgid "blog"
+msgstr "Blog"
-#~ msgid "privacy policy"
-#~ msgstr "隐私政策"
+msgid "privacy policy"
+msgstr "隐私政策"
-#~ msgid "current revision"
-#~ msgstr "当前版本"
+msgid "current revision"
+msgstr "当前版本"
-#~ msgid "number of votes"
-#~ msgstr "票数"
+msgid "number of votes"
+msgstr "票数"
-#~ msgid "current page"
-#~ msgstr "当前页"
+msgid "current page"
+msgstr "当前页"
-#~ msgid "next page"
-#~ msgstr "下一页"
+msgid "next page"
+msgstr "下一页"
-#~ msgid "page number "
-#~ msgstr "第"
+msgid "page number "
+msgstr "第"
-#~ msgid "number - make blank in english"
-#~ msgstr "页"
+msgid "number - make blank in english"
+msgstr "页"
-#~ msgid "Change tags"
-#~ msgstr "修改问题标签"
+msgid "Change tags"
+msgstr "修改问题标签"
# todo: remove magic numbers from this file
-#~ msgid "up to 5 tags, less than 20 characters each"
-#~ msgstr "最多5个标签,每个标签长度小于20个字符。"
-
-#~ msgid "Change now"
-#~ msgstr "现在修改"
-
-#~ msgid "uses tags for the classification of questions"
-#~ msgstr "用标签来分类系统的信息"
-
-#~ msgid "tag editors receive special awards from the community"
-#~ msgstr "修改标签的用户将授予特殊的社区奖牌"
-
-#~ msgid "Why use and modify tags?"
-#~ msgstr "为什么我只能修改问题标签?"
-
-#~ msgid "Found by tag"
-#~ msgstr "标签问题"
-
-#~ msgid "Found by title"
-#~ msgstr "查询结果"
-
-#~ msgid "most recently updated questions"
-#~ msgstr "最近被更新的问题"
-
-#~ msgid "latest questions info"
-#~ msgstr ""
-#~ "问题按<strong>提问时间</strong>显示排序。新加入的问题将显示在最前面。"
-
-#~ msgid ""
-#~ "\n"
-#~ "\t\t\thave total %(q_num)s questions tagged %(tagname)s\n"
-#~ "\t\t\t"
-#~ msgid_plural ""
-#~ "\n"
-#~ "\t\t\thave total %(q_num)s questions tagged %(tagname)s\n"
-#~ "\t\t\t"
-#~ msgstr[0] ""
-#~ "\n"
-#~ "您正在浏览所有<div class=\"questions-count\">%(q_num)s</div>个标记为<span "
-#~ "class=\"tag\">%(tagname)s</span></p>"
-#~ msgstr[1] ""
-#~ "\n"
-#~ "您正在浏览所有<div class=\"questions-count\">%(q_num)s</div>个标记为<span "
-#~ "class=\"tag\">%(tagname)s</span></p>"
-
-#~ msgid ""
-#~ "\n"
-#~ "\t\t\thave total %(q_num)s questions containing %(searchtitle)s\n"
-#~ "\t\t\t"
-#~ msgid_plural ""
-#~ "\n"
-#~ "\t\t\thave total %(q_num)s questions containing %(searchtitle)s\n"
-#~ "\t\t\t"
-#~ msgstr[0] ""
-#~ "\n"
-#~ "您正在浏览所有<div class=\"questions-count\">%(q_num)s</div>个标题含有"
-#~ "<span class=\"tag\">%(searchtitle)s</span></p>"
-#~ msgstr[1] ""
-#~ "\n"
-#~ "您正在浏览所有<div class=\"questions-count\">%(q_num)s</div>个标题含有"
-#~ "<span class=\"tag\">%(searchtitle)s</span></p>"
-
-#~ msgid "number of questions"
-#~ msgstr "个"
-
-#~ msgid "number of <strong>unanswered</strong> questions"
-#~ msgstr ""
-#~ "个 <span class=\"darkred\"><strong>没有回答的</strong></span> 问题。"
-
-#~ msgid "tagged with"
-#~ msgstr "标记为"
-
-#~ msgid "whose title contains"
-#~ msgstr "标题含有"
-
-#~ msgid "number of questions end of sentence"
-#~ msgstr "的问题。"
-
-#~ msgid "Questions are sorted by the <strong>time of last update</strong>."
-#~ msgstr "问题按<strong>最后更新时间</strong>显示排序。"
-
-#~ msgid "Most recently answered ones are shown first."
-#~ msgstr "最后被回答或者>更新的问题将显示在最前面。"
-
-#~ msgid "Questions sorted by <strong>number of responses</strong>."
-#~ msgstr "问题按<strong>回复数量</strong>显示排序。"
-
-#~ msgid "Most answered questions are shown first"
-#~ msgstr "回复最多的问题将显示在最前面。"
-
-#~ msgid "Questions are sorted by the <strong>number of votes</strong>."
-#~ msgstr "问题按<strong>投票数量</strong>显示排序。"
-
-#~ msgid "Most voted questions are shown first"
-#~ msgstr "投票最多的问题将显示在最前面。"
-
-#~ msgid "questions that user selected as his/her favorite"
-#~ msgstr "用户收藏的问题"
-
-#~ msgid "Frequently Asked Questions "
-#~ msgstr "常见问题"
-
-#~ msgid "What kinds of questions can I ask here?"
-#~ msgstr "我可以在这里提问什么样的问题?"
-
-#~ msgid "What questions should I avoid asking?"
-#~ msgstr "什么样的问题我不该在这里提问?"
-
-#~ msgid ""
-#~ "Most importanly - questions should be <strong>relevant</strong> to this "
-#~ "community."
-#~ msgstr "毫无疑问,首先必须是<span class=\"yellowbg\">技术编程问题!</span>"
-
-#~ msgid ""
-#~ "Before asking the question - please make sure to use search to see "
-#~ "whether your question has alredy been answered."
-#~ msgstr ""
-#~ "提问之前,充分利用系统的自动查找、标签和搜索,看看是否已经有一样的问题并有"
-#~ "了答案。"
-
-#~ msgid "What should I avoid in my answers?"
-#~ msgstr "什么样的回答是不受欢迎的?"
-
-#~ msgid "Who moderates this community?"
-#~ msgstr "谁是社区的管理员?"
-
-#~ msgid ""
-#~ "Please avoid asking questions that are not relevant to this community, "
-#~ "too subjective and argumentative."
-#~ msgstr ""
-#~ "<span class=\"yellowbg\">与程序员或技术无关的,引起争吵或太过于主观性等违"
-#~ "背社区宗旨的内容。</span>本站建立是为了帮助大众程序员解决实际技术问题,我"
-#~ "们需要实际的问题!"
-
-#~ msgid ""
-#~ "is a Q&A site, not a discussion group. Therefore - please avoid having "
-#~ "discussions in your answers, comment facility allows some space for brief "
-#~ "discussions."
-#~ msgstr ""
-#~ "希望用户提供针对提问的技术回答,可以是进一步了解问题实质,给予参考方案,或"
-#~ "完全解决问题的回答。我们希望通过问答的形式解决用户的实际问题。因此,<span "
-#~ "class=\"yellowbg\">我们不>欢迎在回答中出现不是回答问题的内容,包括针对他人"
-#~ "回答的讨论,和其他无意义的浪费网络资源行为</span>。CNProg建议您使用<span "
-#~ "class=\"yellowbg\">评论</span>功能来讨论你的意见和想法。"
-
-#~ msgid "The short answer is: <strong>you</strong>."
-#~ msgstr "答案是:<span class=\"yellowbg\">每个用户。</span>"
-
-#~ msgid ""
-#~ "The reputation system allows users earn the authorization to perform a "
-#~ "variety of moderation tasks."
-#~ msgstr ""
-#~ "通过积分运作,<span class=\"yellowbg\">每个用户都有权限创建标签,进行对所"
-#~ "有问题、回答的投票、编辑、关闭等操作。</span>"
-
-#~ msgid "This website is moderated by the users."
-#~ msgstr "社区没有严格意义上的管理员身份"
-
-#~ msgid "How does reputation system work?"
-#~ msgstr "什么是社区积分?"
-
-#~ msgid ""
-#~ "Anyone can ask questions and give answers, points are not necessary for "
-#~ "that."
-#~ msgstr "对于正常使用社区进行提问、回答而言,积分不是必须的。"
-
-#~ msgid ""
-#~ "As we've said before, users help running this site. Point system helps "
-#~ "select users who can administer this community."
-#~ msgstr ""
-#~ "我们一再声明,CNProg由你来运行和维护。如果你想帮助我们来运作CNProg,你需要"
-#~ "一定的积分等级。"
-
-#~ msgid ""
-#~ "Reputation points roughly measure how community trusts you. These points "
-#~ "are given to you directly by other members of the community."
-#~ msgstr ""
-#~ "<span class=\"yellowbg\">积分是一种用来粗略衡量社区对你有多信任的数据。</"
-#~ "span>积分不是有谁来支付或直接给予你的,而是你通过获得其他用户的支持和信"
-#~ "任“赚得”的。"
-
-#~ msgid ""
-#~ "For example, if you ask an interesting question or give a helpful answer, "
-#~ "your input will be upvoted and you will gain more trust in the community."
-#~ msgstr ""
-#~ "举例来说,如果你提了一个非常有帮助的问题或者做了很有用的回答,你将会被其他"
-#~ "用户投赞成票。"
-
-#~ msgid ""
-#~ "If on the other hand someone gives a misleading answer, the answer will "
-#~ "be voted down and he/she loses some points."
-#~ msgstr ""
-#~ "相反,你提了不受欢迎的问题,或者误导用户的回答,你将可能被其他用户投反对"
-#~ "票。每个赞成"
-
-#~ msgid ""
-#~ "Each vote in favor will generate <strong>10</strong> points, each vote "
-#~ "against will subtract <strong>2</strong> points."
-#~ msgstr ""
-#~ "票会帮你产生<strong>10</strong>个社区积分,每个反对票会相应扣除你"
-#~ "<strong>2</strong>个积分。"
-
-#~ msgid ""
-#~ "Through the votes of other people you can accumulate a maximum of "
-#~ "<strong>200</strong> points."
-#~ msgstr ""
-#~ "每天通过别人投赞成票,你最多只能产生<strong>200</strong>个积分,这是上限。"
-
-#~ msgid "After accumulating certain number of points, you can do more:"
-#~ msgstr "当你累计到一定>积分,你可以在社区做更多的事情:"
+msgid "up to 5 tags, less than 20 characters each"
+msgstr "最多5个标签,每个标签长度小于20个字符。"
+
+msgid "Change now"
+msgstr "现在修改"
+
+msgid "uses tags for the classification of questions"
+msgstr "用标签来分类系统的信息"
+
+msgid "tag editors receive special awards from the community"
+msgstr "修改标签的用户将授予特殊的社区奖牌"
+
+msgid "Why use and modify tags?"
+msgstr "为什么我只能修改问题标签?"
+
+msgid "Found by tag"
+msgstr "标签问题"
+
+msgid "Found by title"
+msgstr "查询结果"
+
+msgid "most recently updated questions"
+msgstr "最近被更新的问题"
+
+msgid "latest questions info"
+msgstr ""
+"问题按<strong>提问时间</strong>显示排序。新加入的问题将显示在最前面。"
+
+msgid ""
+"\n"
+"\t\t\thave total %(q_num)s questions tagged %(tagname)s\n"
+"\t\t\t"
+msgid_plural ""
+"\n"
+"\t\t\thave total %(q_num)s questions tagged %(tagname)s\n"
+"\t\t\t"
+msgstr[0] ""
+"\n"
+"您正在浏览所有<div class=\"questions-count\">%(q_num)s</div>个标记为<span "
+"class=\"tag\">%(tagname)s</span></p>"
+msgstr[1] ""
+"\n"
+"您正在浏览所有<div class=\"questions-count\">%(q_num)s</div>个标记为<span "
+"class=\"tag\">%(tagname)s</span></p>"
+
+msgid ""
+"\n"
+"\t\t\thave total %(q_num)s questions containing %(searchtitle)s\n"
+"\t\t\t"
+msgid_plural ""
+"\n"
+"\t\t\thave total %(q_num)s questions containing %(searchtitle)s\n"
+"\t\t\t"
+msgstr[0] ""
+"\n"
+"您正在浏览所有<div class=\"questions-count\">%(q_num)s</div>个标题含有"
+"<span class=\"tag\">%(searchtitle)s</span></p>"
+msgstr[1] ""
+"\n"
+"您正在浏览所有<div class=\"questions-count\">%(q_num)s</div>个标题含有"
+"<span class=\"tag\">%(searchtitle)s</span></p>"
+
+msgid "number of questions"
+msgstr "个"
+
+msgid "number of <strong>unanswered</strong> questions"
+msgstr ""
+"个 <span class=\"darkred\"><strong>没有回答的</strong></span> 问题。"
+
+msgid "tagged with"
+msgstr "标记为"
+
+msgid "whose title contains"
+msgstr "标题含有"
+
+msgid "number of questions end of sentence"
+msgstr "的问题。"
+
+msgid "Questions are sorted by the <strong>time of last update</strong>."
+msgstr "问题按<strong>最后更新时间</strong>显示排序。"
+
+msgid "Most recently answered ones are shown first."
+msgstr "最后被回答或者>更新的问题将显示在最前面。"
+
+msgid "Questions sorted by <strong>number of responses</strong>."
+msgstr "问题按<strong>回复数量</strong>显示排序。"
+
+msgid "Most answered questions are shown first"
+msgstr "回复最多的问题将显示在最前面。"
+
+msgid "Questions are sorted by the <strong>number of votes</strong>."
+msgstr "问题按<strong>投票数量</strong>显示排序。"
+
+msgid "Most voted questions are shown first"
+msgstr "投票最多的问题将显示在最前面。"
+
+msgid "questions that user selected as his/her favorite"
+msgstr "用户收藏的问题"
+
+msgid "Frequently Asked Questions "
+msgstr "常见问题"
+
+msgid "What kinds of questions can I ask here?"
+msgstr "我可以在这里提问什么样的问题?"
+
+msgid "What questions should I avoid asking?"
+msgstr "什么样的问题我不该在这里提问?"
+
+msgid ""
+"Most importanly - questions should be <strong>relevant</strong> to this "
+"community."
+msgstr "毫无疑问,首先必须是<span class=\"yellowbg\">技术编程问题!</span>"
+
+msgid ""
+"Before asking the question - please make sure to use search to see "
+"whether your question has alredy been answered."
+msgstr ""
+"提问之前,充分利用系统的自动查找、标签和搜索,看看是否已经有一样的问题并有"
+"了答案。"
+
+msgid "What should I avoid in my answers?"
+msgstr "什么样的回答是不受欢迎的?"
+
+msgid "Who moderates this community?"
+msgstr "谁是社区的管理员?"
+
+msgid ""
+"Please avoid asking questions that are not relevant to this community, "
+"too subjective and argumentative."
+msgstr ""
+"<span class=\"yellowbg\">与程序员或技术无关的,引起争吵或太过于主观性等违"
+"背社区宗旨的内容。</span>本站建立是为了帮助大众程序员解决实际技术问题,我"
+"们需要实际的问题!"
+
+msgid ""
+"is a Q&A site, not a discussion group. Therefore - please avoid having "
+"discussions in your answers, comment facility allows some space for brief "
+"discussions."
+msgstr ""
+"希望用户提供针对提问的技术回答,可以是进一步了解问题实质,给予参考方案,或"
+"完全解决问题的回答。我们希望通过问答的形式解决用户的实际问题。因此,<span "
+"class=\"yellowbg\">我们不>欢迎在回答中出现不是回答问题的内容,包括针对他人"
+"回答的讨论,和其他无意义的浪费网络资源行为</span>。CNProg建议您使用<span "
+"class=\"yellowbg\">评论</span>功能来讨论你的意见和想法。"
+
+msgid "The short answer is: <strong>you</strong>."
+msgstr "答案是:<span class=\"yellowbg\">每个用户。</span>"
+
+msgid ""
+"The reputation system allows users earn the authorization to perform a "
+"variety of moderation tasks."
+msgstr ""
+"通过积分运作,<span class=\"yellowbg\">每个用户都有权限创建标签,进行对所"
+"有问题、回答的投票、编辑、关闭等操作。</span>"
+
+msgid "This website is moderated by the users."
+msgstr "社区没有严格意义上的管理员身份"
+
+msgid "How does reputation system work?"
+msgstr "什么是社区积分?"
+
+msgid ""
+"Anyone can ask questions and give answers, points are not necessary for "
+"that."
+msgstr "对于正常使用社区进行提问、回答而言,积分不是必须的。"
+
+msgid ""
+"As we've said before, users help running this site. Point system helps "
+"select users who can administer this community."
+msgstr ""
+"我们一再声明,CNProg由你来运行和维护。如果你想帮助我们来运作CNProg,你需要"
+"一定的积分等级。"
+
+msgid ""
+"Reputation points roughly measure how community trusts you. These points "
+"are given to you directly by other members of the community."
+msgstr ""
+"<span class=\"yellowbg\">积分是一种用来粗略衡量社区对你有多信任的数据。</"
+"span>积分不是有谁来支付或直接给予你的,而是你通过获得其他用户的支持和信"
+"任“赚得”的。"
+
+msgid ""
+"For example, if you ask an interesting question or give a helpful answer, "
+"your input will be upvoted and you will gain more trust in the community."
+msgstr ""
+"举例来说,如果你提了一个非常有帮助的问题或者做了很有用的回答,你将会被其他"
+"用户投赞成票。"
+
+msgid ""
+"If on the other hand someone gives a misleading answer, the answer will "
+"be voted down and he/she loses some points."
+msgstr ""
+"相反,你提了不受欢迎的问题,或者误导用户的回答,你将可能被其他用户投反对"
+"票。每个赞成"
+
+msgid ""
+"Each vote in favor will generate <strong>10</strong> points, each vote "
+"against will subtract <strong>2</strong> points."
+msgstr ""
+"票会帮你产生<strong>10</strong>个社区积分,每个反对票会相应扣除你"
+"<strong>2</strong>个积分。"
+
+msgid ""
+"Through the votes of other people you can accumulate a maximum of "
+"<strong>200</strong> points."
+msgstr ""
+"每天通过别人投赞成票,你最多只能产生<strong>200</strong>个积分,这是上限。"
+
+msgid "After accumulating certain number of points, you can do more:"
+msgstr "当你累计到一定>积分,你可以在社区做更多的事情:"
# todo - check if it's indeed plural
-#~ msgid "add comments"
-#~ msgstr "添加评论"
+msgid "add comments"
+msgstr "添加评论"
-#~ msgid "retag questions"
-#~ msgstr "给任何问题整理标签"
+msgid "retag questions"
+msgstr "给任何问题整理标签"
-#~ msgid "edit community wiki questions"
-#~ msgstr "编辑wiki类问题"
+msgid "edit community wiki questions"
+msgstr "编辑wiki类问题"
-#~ msgid "edit any answer"
-#~ msgstr "编辑任何问题或答案"
+msgid "edit any answer"
+msgstr "编辑任何问题或答案"
-#~ msgid "reopen any closed questions"
-#~ msgstr "打开关闭任何人的问题"
+msgid "reopen any closed questions"
+msgstr "打开关闭任何人的问题"
-#~ msgid "delete any comment"
-#~ msgstr "删除任何一个评论"
+msgid "delete any comment"
+msgstr "删除任何一个评论"
-#~ msgid "delete any questions and answers and perform other moderation tasks"
-#~ msgstr "删除任何一个问题或答案,及其他管理功能"
+msgid "delete any questions and answers and perform other moderation tasks"
+msgstr "删除任何一个问题或答案,及其他管理功能"
-#~ msgid "To register, do I need to create new password?"
-#~ msgstr "我需要注册一个新用户吗?"
+msgid "To register, do I need to create new password?"
+msgstr "我需要注册一个新用户吗?"
-#~ msgid "Why other people can edit my questions/answers?"
-#~ msgstr "为什么其他人可以修改我的问题/回答?"
+msgid "Why other people can edit my questions/answers?"
+msgstr "为什么其他人可以修改我的问题/回答?"
-#~ msgid "Still have questions?"
-#~ msgstr "还有其他问题?"
+msgid "Still have questions?"
+msgstr "还有其他问题?"
-#~ msgid "Please ask your question, help make our community better!"
-#~ msgstr "如果您对社区还有其他疑问,请一起来完善我们的"
+msgid "Please ask your question, help make our community better!"
+msgstr "如果您对社区还有其他疑问,请一起来完善我们的"
-#~ msgid ""
-#~ "No, you don't have to. You can login through any service that supports "
-#~ "OpenID, e.g. Google, Yahoo, AOL, etc."
-#~ msgstr ""
-#~ "不需要。社区提供了OpenID的登录支持,你要用Google、Yahoo等任何支持OpenID登"
-#~ "录的帐号就可以使用系统。"
+msgid ""
+"No, you don't have to. You can login through any service that supports "
+"OpenID, e.g. Google, Yahoo, AOL, etc."
+msgstr ""
+"不需要。社区提供了OpenID的登录支持,你要用Google、Yahoo等任何支持OpenID登"
+"录的帐号就可以使用系统。"
-#~ msgid "Login now!"
-#~ msgstr "马上登录"
+msgid "Login now!"
+msgstr "马上登录"
-#~ 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 ""
-#~ "所以问题和答案都是如Wiki一样可编辑的,我们希望社区能帮助用户沉淀、积累更多"
-#~ "有用的知识和经验。"
+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 ""
+"所以问题和答案都是如Wiki一样可编辑的,我们希望社区能帮助用户沉淀、积累更多"
+"有用的知识和经验。"
-#~ msgid "If this approach is not for you, we respect your choice."
-#~ msgstr "如果您不喜欢这种方式,我们尊重你的选择。"
+msgid "If this approach is not for you, we respect your choice."
+msgstr "如果您不喜欢这种方式,我们尊重你的选择。"
-#~ msgid "answer tips"
-#~ msgstr "受欢迎的提问"
+msgid "answer tips"
+msgstr "受欢迎的提问"
-#~ msgid "try to give an answer, rather than engage into a discussion"
-#~ msgstr "建议您提的问题是可以被答复的,而不仅仅是可以讨论。"
+msgid "try to give an answer, rather than engage into a discussion"
+msgstr "建议您提的问题是可以被答复的,而不仅仅是可以讨论。"
-#~ msgid "gold badge: the highest honor and is very rare"
-#~ msgstr "金牌:十分罕见之最高荣耀"
+msgid "gold badge: the highest honor and is very rare"
+msgstr "金牌:十分罕见之最高荣耀"
-#~ msgid ""
-#~ "silver badge: occasionally awarded for the very high quality contributions"
-#~ msgstr "银牌:偶尔颁发之优质奖章"
+msgid ""
+"silver badge: occasionally awarded for the very high quality contributions"
+msgstr "银牌:偶尔颁发之优质奖章"
-#~ msgid "Gold badge is very rare."
-#~ msgstr "金牌是十分罕见的。"
+msgid "Gold badge is very rare."
+msgstr "金牌是十分罕见的。"
-#~ msgid "Gold badge is the highest award in this community."
-#~ msgstr "获得金牌意味着你在某个层次上已经达到了顶峰。"
+msgid "Gold badge is the highest award in this community."
+msgstr "获得金牌意味着你在某个层次上已经达到了顶峰。"
-#~ msgid "Obtaining silver badge requires significant patience."
-#~ msgstr "银牌需要经过长时间的奋斗才能获得。"
+msgid "Obtaining silver badge requires significant patience."
+msgstr "银牌需要经过长时间的奋斗才能获得。"
-#~ msgid "%s ago"
-#~ msgstr "于%s<font class=\"darkred\">关闭</font>"
+msgid "%s ago"
+msgstr "于%s<font class=\"darkred\">关闭</font>"
diff --git a/middleware/__init__.py b/middleware/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/middleware/__init__.py
+++ /dev/null
diff --git a/mikes.patch b/mikes.patch
new file mode 100644
index 00000000..58437fb1
--- /dev/null
+++ b/mikes.patch
@@ -0,0 +1,2862 @@
+diff -ruN CNPROG/context.py mikes/context.py
+--- CNPROG/context.py 1969-12-31 19:00:00.000000000 -0500
++++ mikes/context.py 2009-07-25 19:09:58.098151134 -0400
+@@ -0,0 +1,9 @@
++from django.conf import settings
++def application_settings(context):
++ return {
++ 'APP_TITLE' : settings.APP_TITLE,
++ 'APP_URL' : settings.APP_URL,
++ 'APP_KEYWORDS' : settings.APP_KEYWORDS,
++ 'APP_DESCRIPTION' : settings.APP_DESCRIPTION,
++ 'APP_INTRO' : settings.APP_INTRO
++ }
+diff -ruN CNPROG/development.log mikes/development.log
+--- CNPROG/development.log 1969-12-31 19:00:00.000000000 -0500
++++ mikes/development.log 2009-07-25 19:09:58.098151134 -0400
+@@ -0,0 +1 @@
++# development log
+\ No newline at end of file
+diff -ruN CNPROG/django_authopenid/models.py mikes/django_authopenid/models.py
+--- CNPROG/django_authopenid/models.py 2009-06-22 21:42:50.000000000 -0400
++++ mikes/django_authopenid/models.py 2009-07-25 19:09:58.098151134 -0400
+@@ -3,7 +3,7 @@
+ from django.contrib.auth.models import User
+ from django.db import models
+
+-import md5, random, sys, os, time
++import hashlib, random, sys, os, time
+
+ __all__ = ['Nonce', 'Association', 'UserAssociation',
+ 'UserPasswordQueueManager', 'UserPasswordQueue']
+@@ -47,7 +47,7 @@
+ # The random module is seeded when this Apache child is created.
+ # Use SECRET_KEY as added salt.
+ while 1:
+- confirm_key = md5.new("%s%s%s%s" % (
++ confirm_key = hashlib.md5("%s%s%s%s" % (
+ random.randint(0, sys.maxint - 1), os.getpid(),
+ time.time(), settings.SECRET_KEY)).hexdigest()
+ try:
+diff -ruN CNPROG/django_authopenid/util.py mikes/django_authopenid/util.py
+--- CNPROG/django_authopenid/util.py 2009-06-22 21:42:50.000000000 -0400
++++ mikes/django_authopenid/util.py 2009-07-25 19:09:58.098151134 -0400
+@@ -15,7 +15,7 @@
+ except:
+ from yadis import xri
+
+-import time, base64, md5, operator
++import time, base64, hashlib, operator
+ import urllib
+
+ from models import Association, Nonce
+@@ -128,7 +128,7 @@
+
+ def getAuthKey(self):
+ # Use first AUTH_KEY_LEN characters of md5 hash of SECRET_KEY
+- return md5.new(settings.SECRET_KEY).hexdigest()[:self.AUTH_KEY_LEN]
++ return hashlib.md5(settings.SECRET_KEY).hexdigest()[:self.AUTH_KEY_LEN]
+
+ def isDumb(self):
+ return False
+diff -ruN CNPROG/forum/const.py mikes/forum/const.py
+--- CNPROG/forum/const.py 2009-07-26 16:01:31.559063617 -0400
++++ mikes/forum/const.py 2009-07-25 19:09:58.098151134 -0400
+@@ -53,22 +52,24 @@
+ #TYPE_ACTIVITY_EDIT_ANSWER=18
+
+ TYPE_ACTIVITY = (
+ (TYPE_ACTIVITY_ASK_QUESTION, _('question')),
+ (TYPE_ACTIVITY_ANSWER, _('answer')),
+ (TYPE_ACTIVITY_COMMENT_QUESTION, _('commented question')),
+ (TYPE_ACTIVITY_COMMENT_ANSWER, _('commented answer')),
+ (TYPE_ACTIVITY_UPDATE_QUESTION, _('edited question')),
+ (TYPE_ACTIVITY_UPDATE_ANSWER, _('edited answer')),
+ (TYPE_ACTIVITY_PRIZE, _('received award')),
+ (TYPE_ACTIVITY_MARK_ANSWER, _('marked best answer')),
+ (TYPE_ACTIVITY_VOTE_UP, _('upvoted')),
+ (TYPE_ACTIVITY_VOTE_DOWN, _('downvoted')),
+ (TYPE_ACTIVITY_CANCEL_VOTE, _('canceled vote')),
+ (TYPE_ACTIVITY_DELETE_QUESTION, _('deleted question')),
+ (TYPE_ACTIVITY_DELETE_ANSWER, _('deleted answer')),
+ (TYPE_ACTIVITY_MARK_OFFENSIVE, _('marked offensive')),
+ (TYPE_ACTIVITY_UPDATE_TAGS, _('updated tags')),
+ (TYPE_ACTIVITY_FAVORITE, _('selected favorite')),
+ (TYPE_ACTIVITY_USER_FULL_UPDATED, _('completed user profile')),
++ #(TYPE_ACTIVITY_EDIT_QUESTION, u'编辑问题'),
++ #(TYPE_ACTIVITY_EDIT_ANSWER, u'编辑答案'),
+ )
+
+diff -ruN CNPROG/forum/management/commands/once_award_badges.py mikes/forum/management/commands/once_award_badges.py
+--- CNPROG/forum/management/commands/once_award_badges.py 2009-06-22 21:42:50.000000000 -0400
++++ mikes/forum/management/commands/once_award_badges.py 2009-07-25 19:09:58.098151134 -0400
+@@ -157,7 +157,8 @@
+ """
+ activity_types = ','.join('%s' % item for item in BADGE_AWARD_TYPE_FIRST.keys())
+ # ORDER BY user_id, activity_type
+- query = "SELECT id, user_id, activity_type, content_type_id, object_id FROM activity WHERE is_auditted = 0 AND activity_type IN (%s) ORDER BY user_id, activity_type" % activity_types
++ query = "SELECT id, user_id, activity_type, content_type_id, object_id "+
++ "FROM activity WHERE is_auditted = 0 AND activity_type IN (%s) ORDER BY user_id, activity_type" % activity_types
+
+ cursor = connection.cursor()
+ try:
+@@ -205,7 +206,10 @@
+
+ (13, '学生', 3, '学生', '第一次提问并且有一次以上赞成票', 0, 0),
+ """
+- query = "SELECT act.user_id, q.vote_up_count, act.object_id FROM activity act, question q WHERE act.activity_type = %s AND act.object_id = q.id AND act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ASK_QUESTION, 13)
++ query = "SELECT act.user_id, q.vote_up_count, act.object_id FROM "+
++ "activity act, question q WHERE act.activity_type = %s AND "+
++ "act.object_id = q.id AND "+
++ "act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ASK_QUESTION, 13)
+ cursor = connection.cursor()
+ try:
+ cursor.execute(query)
+@@ -232,7 +236,10 @@
+
+ (15, '教师', 3, '教师', '第一次回答问题并且得到一个以上赞成票', 0, 0),
+ """
+- query = "SELECT act.user_id, a.vote_up_count, act.object_id FROM activity act, answer a WHERE act.activity_type = %s AND act.object_id = a.id AND act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 15)
++ query = "SELECT act.user_id, a.vote_up_count, act.object_id FROM "+
++ "activity act, answer a WHERE act.activity_type = %s AND "+
++ "act.object_id = a.id AND "+
++ "act.user_id NOT IN (SELECT distinct user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 15)
+ cursor = connection.cursor()
+ try:
+ cursor.execute(query)
+@@ -257,7 +264,11 @@
+ """
+ (32, '学问家', 2, '学问家', '第一次回答被投赞成票10次以上', 0, 0)
+ """
+- query = "SELECT act.user_id, act.object_id FROM activity act, answer a WHERE act.object_id = a.id AND act.activity_type = %s AND a.vote_up_count >= 10 AND act.user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 32)
++ query = "SELECT act.user_id, act.object_id FROM "+
++ "activity act, answer a WHERE act.object_id = a.id AND "+
++ "act.activity_type = %s AND "+
++ "a.vote_up_count >= 10 AND "+
++ "act.user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s)" % (TYPE_ACTIVITY_ANSWER, 32)
+ cursor = connection.cursor()
+ try:
+ cursor.execute(query)
+@@ -281,7 +292,11 @@
+ """
+ (26, '优秀市民', 2, '优秀市民', '投票300次以上', 0, 0)
+ """
+- query = "SELECT count(*) vote_count, user_id FROM activity WHERE activity_type = %s OR activity_type = %s AND user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) GROUP BY user_id HAVING vote_count >= 300" % (TYPE_ACTIVITY_VOTE_UP, TYPE_ACTIVITY_VOTE_DOWN, 26)
++ query = "SELECT count(*) vote_count, user_id FROM activity WHERE "+
++ "activity_type = %s OR "+
++ "activity_type = %s AND "+
++ "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) "+
++ "GROUP BY user_id HAVING vote_count >= 300" % (TYPE_ACTIVITY_VOTE_UP, TYPE_ACTIVITY_VOTE_DOWN, 26)
+
+ self.__award_for_count_num(query, 26)
+
+@@ -289,7 +304,11 @@
+ """
+ (27, '编辑主任', 2, '编辑主任', '编辑了100个帖子', 0, 0)
+ """
+- query = "SELECT count(*) vote_count, user_id FROM activity WHERE activity_type = %s OR activity_type = %s AND user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) GROUP BY user_id HAVING vote_count >= 100" % (TYPE_ACTIVITY_UPDATE_QUESTION, TYPE_ACTIVITY_UPDATE_ANSWER, 27)
++ query = "SELECT count(*) vote_count, user_id FROM activity WHERE "+
++ "activity_type = %s OR "+
++ "activity_type = %s AND "+
++ "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) "+
++ "GROUP BY user_id HAVING vote_count >= 100" % (TYPE_ACTIVITY_UPDATE_QUESTION, TYPE_ACTIVITY_UPDATE_ANSWER, 27)
+
+ self.__award_for_count_num(query, 27)
+
+@@ -297,7 +316,11 @@
+ """
+ (5, '评论家', 3, '评论家', '评论10次以上', 0, 0),
+ """
+- query = "SELECT count(*) vote_count, user_id FROM activity WHERE activity_type = %s OR activity_type = %s AND user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) GROUP BY user_id HAVING vote_count >= 10" % (TYPE_ACTIVITY_COMMENT_QUESTION, TYPE_ACTIVITY_COMMENT_ANSWER, 5)
++ query = "SELECT count(*) vote_count, user_id FROM activity WHERE "+
++ "activity_type = %s OR "+
++ "activity_type = %s AND "+
++ "user_id NOT IN (SELECT user_id FROM award WHERE badge_id = %s) "+
++ "GROUP BY user_id HAVING vote_count >= 10" % (TYPE_ACTIVITY_COMMENT_QUESTION, TYPE_ACTIVITY_COMMENT_ANSWER, 5)
+ self.__award_for_count_num(query, 5)
+
+ def __award_for_count_num(self, query, badge):
+diff -ruN CNPROG/forum/managers.py mikes/forum/managers.py
+--- CNPROG/forum/managers.py 2009-06-22 21:42:50.000000000 -0400
++++ mikes/forum/managers.py 2009-07-25 19:09:58.098151134 -0400
+@@ -4,8 +4,29 @@
+ from django.db import connection, models, transaction
+ from django.db.models import Q
+ from forum.models import *
++from urllib import quote, unquote
+
+ class QuestionManager(models.Manager):
++ def get_translation_questions(self, orderby, page_size):
++ questions = self.filter(deleted=False, author__id__in=[28,29]).order_by(orderby)[:page_size]
++ return questions
++
++ def get_questions_by_pagesize(self, orderby, page_size):
++ questions = self.filter(deleted=False).order_by(orderby)[:page_size]
++ return questions
++
++ def get_questions_by_tag(self, tagname, orderby):
++ questions = self.filter(deleted=False, tags__name = unquote(tagname)).order_by(orderby)
++ return questions
++
++ def get_unanswered_questions(self, orderby):
++ questions = self.filter(deleted=False, answer_count=0).order_by(orderby)
++ return questions
++
++ def get_questions(self, orderby):
++ questions = self.filter(deleted=False).order_by(orderby)
++ return questions
++
+ def update_tags(self, question, tagnames, user):
+ """
+ Updates Tag associations for a question to match the given
+@@ -92,7 +113,12 @@
+ 'WHERE tag_id = tag.id'
+ ') '
+ '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]
++ return tags
++
+ def get_or_create_multiple(self, names, user):
+ """
+ Fetches a list of Tags with the given names, creating any Tags
+@@ -123,6 +149,19 @@
+ query = self.UPDATE_USED_COUNTS_QUERY % ','.join(['%s'] * len(tags))
+ cursor.execute(query, [tag.id for tag in tags])
+ transaction.commit_unless_managed()
++
++ def get_tags_by_questions(self, questions):
++ question_ids = []
++ for question in questions:
++ question_ids.append(question.id)
++
++ question_ids_str = ','.join([str(id) for id in question_ids])
++ related_tags = self.extra(
++ tables=['tag', 'question_tags'],
++ where=["tag.id = question_tags.tag_id AND question_tags.question_id IN (" + question_ids_str + ")"]
++ ).distinct()
++
++ return related_tags
+
+ class AnswerManager(models.Manager):
+ GET_ANSWERS_FROM_USER_QUESTIONS = u'SELECT answer.* FROM answer INNER JOIN question ON answer.question_id = question.id WHERE question.author_id =%s AND answer.author_id <> %s'
+@@ -205,4 +244,16 @@
+ return row[0]
+
+ else:
+- return 0
+\ No newline at end of file
++ return 0
++class AwardManager(models.Manager):
++ def get_recent_awards(self):
++ awards = super(AwardManager, self).extra(
++ select={'badge_id': 'badge.id', 'badge_name':'badge.name',
++ 'badge_description': 'badge.description', 'badge_type': 'badge.type',
++ 'user_id': 'auth_user.id', 'user_name': 'auth_user.username'
++ },
++ tables=['award', 'badge', 'auth_user'],
++ order_by=['-awarded_at'],
++ where=['auth_user.id=award.user_id AND badge_id=badge.id'],
++ ).values('badge_id', 'badge_name', 'badge_description', 'badge_type', 'user_id', 'user_name')
++ return awards
+diff -ruN CNPROG/forum/models.py mikes/forum/models.py
+--- CNPROG/forum/models.py 2009-06-22 21:42:50.000000000 -0400
++++ mikes/forum/models.py 2009-07-25 19:09:58.108151006 -0400
+@@ -351,7 +350,8 @@
+ content_object = generic.GenericForeignKey('content_type', 'object_id')
+ awarded_at = models.DateTimeField(default=datetime.datetime.now)
+ notified = models.BooleanField(default=False)
+-
++ objects = AwardManager()
++
+ def __unicode__(self):
+ return u'[%s] is awarded a badge [%s] at %s' % (self.user.username, self.badge.name, self.awarded_at)
+
+diff -ruN CNPROG/forum/templatetags/extra_tags.py mikes/forum/templatetags/extra_tags.py
+--- CNPROG/forum/templatetags/extra_tags.py 2009-06-22 21:42:50.000000000 -0400
++++ mikes/forum/templatetags/extra_tags.py 2009-07-25 19:09:58.108151006 -0400
+@@ -1,4 +1,4 @@
+-import time
++import time
+ import datetime
+ import math
+ import re
+@@ -50,10 +49,10 @@
+ weight = 0
+ return MIN_FONTSIZE + round((MAX_FONTSIZE - MIN_FONTSIZE) * weight)
+
+-
++
+ LEADING_PAGE_RANGE_DISPLAYED = TRAILING_PAGE_RANGE_DISPLAYED = 5
+ LEADING_PAGE_RANGE = TRAILING_PAGE_RANGE = 4
+-NUM_PAGES_OUTSIDE_RANGE = 1
++NUM_PAGES_OUTSIDE_RANGE = 1
+ ADJACENT_PAGES = 2
+ @register.inclusion_tag("paginator.html")
+ def cnprog_paginator(context):
+@@ -65,10 +64,10 @@
+ " Initialize variables "
+ in_leading_range = in_trailing_range = False
+ pages_outside_leading_range = pages_outside_trailing_range = range(0)
+-
++
+ if (context["pages"] <= LEADING_PAGE_RANGE_DISPLAYED):
+ in_leading_range = in_trailing_range = True
+- page_numbers = [n for n in range(1, context["pages"] + 1) if n > 0 and n <= context["pages"]]
++ page_numbers = [n for n in range(1, context["pages"] + 1) if n > 0 and n <= context["pages"]]
+ elif (context["page"] <= LEADING_PAGE_RANGE):
+ in_leading_range = True
+ page_numbers = [n for n in range(1, LEADING_PAGE_RANGE_DISPLAYED + 1) if n > 0 and n <= context["pages"]]
+@@ -77,11 +76,11 @@
+ in_trailing_range = True
+ page_numbers = [n for n in range(context["pages"] - TRAILING_PAGE_RANGE_DISPLAYED + 1, context["pages"] + 1) if n > 0 and n <= context["pages"]]
+ pages_outside_trailing_range = [n + 1 for n in range(0, NUM_PAGES_OUTSIDE_RANGE)]
+- else:
++ else:
+ page_numbers = [n for n in range(context["page"] - ADJACENT_PAGES, context["page"] + ADJACENT_PAGES + 1) if n > 0 and n <= context["pages"]]
+ pages_outside_leading_range = [n + context["pages"] for n in range(0, -NUM_PAGES_OUTSIDE_RANGE, -1)]
+ pages_outside_trailing_range = [n + 1 for n in range(0, NUM_PAGES_OUTSIDE_RANGE)]
+-
++
+ extend_url = context.get('extend_url', '')
+ return {
+ "base_url": context["base_url"],
+@@ -205,12 +197,12 @@
+ m = re.match(pattern, strValue)
+ return first + result
+
+-@register.simple_tag
++@register.simple_tag
+ def convert2tagname_list(question):
+ question['tagnames'] = [name for name in question['tagnames'].split(u' ')]
+ return ''
+
+-@register.simple_tag
++@register.simple_tag
+ def diff_date(date, limen=2):
+ current_time = datetime.datetime(*time.localtime()[0:6])
+ diff = current_time - date
+@@ -237,4 +229,4 @@
+ timestr = strftime("%H:%M %b-%d-%Y %Z", localtime(latest))
+ except:
+ timestr = ''
+- return timestr
++ return timestr
+\ No newline at end of file
+diff -ruN CNPROG/forum/user.py mikes/forum/user.py
+--- CNPROG/forum/user.py 2009-06-22 21:42:50.000000000 -0400
++++ mikes/forum/user.py 2009-07-25 19:09:58.108151006 -0400
+@@ -1,3 +1,4 @@
++# coding=utf-8
+ from django.utils.translation import ugettext as _
+ class UserView:
+ def __init__(self, id, tab_title, tab_description, page_title, view_name, template_file, data_size=0):
+diff -ruN CNPROG/forum/views.py mikes/forum/views.py
+--- CNPROG/forum/views.py 2009-06-22 21:42:50.000000000 -0400
++++ mikes/forum/views.py 2009-07-25 19:09:58.108151006 -0400
+@@ -77,29 +76,17 @@
+ orderby = "-last_activity_at"
+ # group questions by author_id of 28,29
+ if view_id == 'trans':
+- questions = Question.objects.filter(deleted=False, author__id__in=[28,29]).order_by(orderby)[:INDEX_PAGE_SIZE]
++ questions = Question.objects.get_translation_questions(orderby, INDEX_PAGE_SIZE)
+ else:
+- questions = Question.objects.filter(deleted=False).order_by(orderby)[:INDEX_PAGE_SIZE]
++ questions = Question.objects.get_questions_by_pagesize(orderby, INDEX_PAGE_SIZE)
+ # RISK - inner join queries
+- questions = questions.select_related();
+- tags = Tag.objects.all().filter(deleted=False).exclude(used_count=0).order_by("-id")[:INDEX_TAGS_SIZE]
++ questions = questions.select_related()
++ tags = Tag.objects.get_valid_tags(INDEX_TAGS_SIZE)
+
+- awards = Award.objects.extra(
+- select={'badge_id': 'badge.id', 'badge_name':'badge.name',
+- 'badge_description': 'badge.description', 'badge_type': 'badge.type',
+- 'user_id': 'auth_user.id', 'user_name': 'auth_user.username'
+- },
+- tables=['award', 'badge', 'auth_user'],
+- order_by=['-awarded_at'],
+- where=['auth_user.id=award.user_id AND badge_id=badge.id'],
+- ).values('badge_id', 'badge_name', 'badge_description', 'badge_type', 'user_id', 'user_name')
+-
+- class testvar:
+- content = 'haha'
++ awards = Award.objects.get_recent_awards()
+
+ return render_to_response('index.html', {
+ "questions" : questions,
+- 'testvar':testvar,
+ "tab_id" : view_id,
+ "tags" : tags,
+ "awards" : awards[:INDEX_AWARD_SIZE],
+@@ -127,29 +114,11 @@
+ # Set flag to False by default. If it is equal to True, then need to be saved.
+ pagesize_changed = False
+ # get pagesize from session, if failed then get default value
+- user_page_size = request.session.get("pagesize", QUESTIONS_PAGE_SIZE)
+- # set pagesize equal to logon user specified value in database
+- if request.user.is_authenticated() and request.user.questions_per_page > 0:
+- user_page_size = request.user.questions_per_page
+-
++ pagesize = request.session.get("pagesize")
+ try:
+ page = int(request.GET.get('page', '1'))
+- # get new pagesize from UI selection
+- pagesize = int(request.GET.get('pagesize', user_page_size))
+- if pagesize <> user_page_size:
+- pagesize_changed = True
+-
+ except ValueError:
+ page = 1
+- pagesize = user_page_size
+-
+- # save this pagesize to user database
+- if pagesize_changed:
+- request.session["pagesize"] = pagesize
+- if request.user.is_authenticated():
+- user = request.user
+- user.questions_per_page = pagesize
+- user.save()
+
+ view_id = request.GET.get('sort', None)
+ view_dic = {"latest":"-added_at", "active":"-last_activity_at", "hottest":"-answer_count", "mostvoted":"-score" }
+@@ -161,29 +130,24 @@
+
+ # check if request is from tagged questions
+ if tagname is not None:
+- #print datetime.datetime.now()
+- objects = Question.objects.filter(deleted=False, tags__name = unquote(tagname)).order_by(orderby)
+- #print datetime.datetime.now()
++ objects = Question.objects.get_questions_by_tag(tagname, orderby)
+ elif unanswered:
+ #check if request is from unanswered questions
+ template_file = "unanswered.html"
+- objects = Question.objects.filter(deleted=False, answer_count=0).order_by(orderby)
++ objects = Question.objects.get_unanswered_questions(orderby)
+ else:
+- objects = Question.objects.filter(deleted=False).order_by(orderby)
++ objects = Question.objects.get_questions(orderby)
+
+ # RISK - inner join queries
+- objects = objects.select_related();
++ objects = objects.select_related(depth=1);
+ objects_list = Paginator(objects, pagesize)
+ questions = objects_list.page(page)
+
+ # Get related tags from this page objects
+- related_tags = []
+- for question in questions.object_list:
+- tags = list(question.tags.all())
+- for tag in tags:
+- if tag not in related_tags:
+- related_tags.append(tag)
+-
++ if questions.object_list.count() > 0:
++ related_tags = Tag.objects.get_tags_by_questions(questions.object_list)
++ else:
++ related_tags = None
+ return render_to_response(template_file, {
+ "questions" : questions,
+ "tab_id" : view_id,
+@@ -1022,6 +986,7 @@
+ 'title',
+ 'author_id',
+ 'accepted',
++ 'vote_count',
+ 'answer_count',
+ 'vote_up_count',
+ 'vote_down_count')[:100]
+@@ -1090,7 +1055,8 @@
+ 'activity_type' : 'activity.activity_type'
+ },
+ 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'],
++ where=['activity.content_type_id = %s AND activity.object_id = ' +
++ 'question.id 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(
+@@ -1114,8 +1080,8 @@
+ 'activity_type' : 'activity.activity_type'
+ },
+ 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'],
++ 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'],
+ params=[answer_type_id, user_id, TYPE_ACTIVITY_ANSWER],
+ order_by=['-activity.active_at']
+ ).values(
+@@ -1140,7 +1106,9 @@
+ },
+ tables=['activity', 'question', 'comment'],
+
+- 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'],
++ 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'],
+ params=[comment_type_id, question_type_id, user_id, TYPE_ACTIVITY_COMMENT_QUESTION],
+ order_by=['-comment.added_at']
+ ).values(
+@@ -1166,7 +1134,10 @@
+ },
+ tables=['activity', 'question', 'answer', 'comment'],
+
+- 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'],
++ 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'],
+ params=[comment_type_id, answer_type_id, user_id, TYPE_ACTIVITY_COMMENT_ANSWER],
+ order_by=['-comment.added_at']
+ ).values(
+@@ -1192,7 +1163,9 @@
+ 'summary' : 'question_revision.summary'
+ },
+ tables=['activity', 'question_revision'],
+- where=['activity.content_type_id = %s AND activity.object_id = question_revision.id AND activity.user_id = question_revision.author_id AND activity.user_id = %s AND activity.activity_type=%s'],
++ where=['activity.content_type_id = %s AND activity.object_id = question_revision.id 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],
+ order_by=['-activity.active_at']
+ ).values(
+@@ -1220,7 +1193,10 @@
+ },
+ tables=['activity', 'answer_revision', 'question', 'answer'],
+
+- 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 activity.activity_type=%s'],
++ 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 '+
++ 'activity.activity_type=%s'],
+ params=[answer_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_ANSWER],
+ order_by=['-activity.active_at']
+ ).values(
+@@ -1246,7 +1222,9 @@
+ 'activity_type' : 'activity.activity_type',
+ },
+ 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.question_id=question.id AND activity.activity_type=%s'],
++ 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.question_id=question.id AND activity.activity_type=%s'],
+ params=[answer_type_id, user_id, TYPE_ACTIVITY_MARK_ANSWER],
+ order_by=['-activity.active_at']
+ ).values(
+@@ -1267,7 +1245,8 @@
+ 'activity_type' : 'activity.activity_type'
+ },
+ tables=['activity', 'award', 'badge'],
+- where=['activity.user_id = award.user_id AND activity.user_id = %s AND award.badge_id=badge.id AND activity.object_id=award.id AND activity.activity_type=%s'],
++ where=['activity.user_id = award.user_id AND activity.user_id = %s AND '+
++ 'award.badge_id=badge.id AND activity.object_id=award.id AND activity.activity_type=%s'],
+ params=[user_id, TYPE_ACTIVITY_PRIZE],
+ order_by=['-activity.active_at']
+ ).values(
+@@ -1320,7 +1299,8 @@
+ },
+ select_params=[user_id],
+ tables=['answer', 'question', 'auth_user'],
+- where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND question.author_id = %s AND answer.author_id <> %s AND answer.author_id=auth_user.id'],
++ where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND '+
++ 'question.author_id = %s AND answer.author_id <> %s AND answer.author_id=auth_user.id'],
+ params=[user_id, user_id],
+ order_by=['-answer.id']
+ ).values(
+@@ -1349,7 +1329,8 @@
+ 'user_id' : 'auth_user.id'
+ },
+ tables=['question', 'auth_user', 'comment'],
+- where=['question.deleted = 0 AND question.author_id = %s AND comment.object_id=question.id AND comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id'],
++ where=['question.deleted = 0 AND question.author_id = %s AND comment.object_id=question.id AND '+
++ 'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id'],
+ params=[user_id, question_type_id, user_id],
+ order_by=['-comment.added_at']
+ ).values(
+@@ -1378,7 +1359,9 @@
+ 'user_id' : 'auth_user.id'
+ },
+ tables=['answer', 'auth_user', 'comment', 'question'],
+- where=['answer.deleted = 0 AND answer.author_id = %s AND comment.object_id=answer.id AND comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id AND question.id = answer.question_id'],
++ where=['answer.deleted = 0 AND answer.author_id = %s AND comment.object_id=answer.id AND '+
++ 'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id '+
++ 'AND question.id = answer.question_id'],
+ params=[user_id, answer_type_id, user_id],
+ order_by=['-comment.added_at']
+ ).values(
+@@ -1409,7 +1392,8 @@
+ },
+ select_params=[user_id],
+ tables=['answer', 'question', 'auth_user'],
+- where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND answer.author_id = %s AND answer.accepted=1 AND question.author_id=auth_user.id'],
++ where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND '+
++ 'answer.author_id = %s AND answer.accepted=1 AND question.author_id=auth_user.id'],
+ params=[user_id],
+ order_by=['-answer.id']
+ ).values(
+@@ -1453,7 +1437,8 @@
+ },
+ select_params=[user_id],
+ tables=['vote', 'question', 'auth_user'],
+- where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = question.id AND vote.user_id=auth_user.id'],
++ where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = question.id '+
++ 'AND vote.user_id=auth_user.id'],
+ params=[question_type_id, user_id],
+ order_by=['-vote.id']
+ ).values(
+@@ -1476,7 +1461,8 @@
+ },
+ select_params=[user_id],
+ tables=['vote', 'answer', 'question', 'auth_user'],
+- where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = answer.id AND answer.question_id = question.id AND vote.user_id=auth_user.id'],
++ where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = answer.id '+
++ 'AND answer.question_id = question.id AND vote.user_id=auth_user.id'],
+ params=[answer_type_id, user_id],
+ order_by=['-vote.id']
+ ).values(
+@@ -1501,7 +1487,8 @@
+ def user_reputation(request, user_id, user_view):
+ user = get_object_or_404(User, id=user_id)
+ reputation = Repute.objects.extra(
+- select={'positive': 'sum(positive)', 'negative': 'sum(negative)', 'question_id':'question_id', 'title': 'question.title'},
++ select={'positive': 'sum(positive)', 'negative': 'sum(negative)', 'question_id':'question_id',
++ 'title': 'question.title'},
+ tables=['repute', 'question'],
+ order_by=['-reputed_at'],
+ where=['user_id=%s AND question_id=question.id'],
+@@ -1510,6 +1497,7 @@
+
+ reputation.query.group_by = ['question_id']
+
++
+ rep_list = []
+ for rep in Repute.objects.filter(user=user).order_by('reputed_at'):
+ dic = '[%s,%s]' % (calendar.timegm(rep.reputed_at.timetuple()) * 1000, rep.reputation)
+@@ -1531,7 +1519,8 @@
+ questions = Question.objects.extra(
+ select={
+ 'vote_count' : 'question.vote_up_count + question.vote_down_count',
+- 'favorited_myself' : 'SELECT count(*) FROM favorite_question f WHERE f.user_id = %s AND f.question_id = question.id',
++ 'favorited_myself' : 'SELECT count(*) FROM favorite_question f WHERE f.user_id = %s '+
++ 'AND f.question_id = question.id',
+ 'la_user_id' : 'auth_user.id',
+ 'la_username' : 'auth_user.username',
+ 'la_user_gold' : 'auth_user.gold',
+@@ -1541,7 +1530,8 @@
+ },
+ select_params=[user_id],
+ tables=['question', 'auth_user', 'favorite_question'],
+- where=['question.deleted = 0 AND question.last_activity_by_id = auth_user.id AND favorite_question.question_id = question.id AND favorite_question.user_id = %s'],
++ where=['question.deleted = 0 AND question.last_activity_by_id = auth_user.id '+
++ 'AND favorite_question.question_id = question.id AND favorite_question.user_id = %s'],
+ params=[user_id],
+ order_by=['-vote_count', '-question.id']
+ ).values('vote_count',
+@@ -1672,7 +1662,12 @@
+ def badge(request, id):
+ badge = get_object_or_404(Badge, id=id)
+ awards = Award.objects.extra(
+- select={'id': 'auth_user.id', 'name': 'auth_user.username', 'rep':'auth_user.reputation', 'gold': 'auth_user.gold', 'silver': 'auth_user.silver', 'bronze': 'auth_user.bronze'},
++ select={'id': 'auth_user.id',
++ 'name': 'auth_user.username',
++ 'rep':'auth_user.reputation',
++ 'gold': 'auth_user.gold',
++ 'silver': 'auth_user.silver',
++ 'bronze': 'auth_user.bronze'},
+ tables=['award', 'auth_user'],
+ where=['badge_id=%s AND user_id=auth_user.id'],
+ params=[id]
+diff -ruN CNPROG/INSTALL mikes/INSTALL
+--- CNPROG/INSTALL 1969-12-31 19:00:00.000000000 -0500
++++ mikes/INSTALL 2009-07-25 19:09:58.068150962 -0400
+@@ -0,0 +1,33 @@
++PRE-REQUIREMENTS:
++-----------------------------------------------
++1. Python2.5, MySQL, Django v1.0+
++
++2. Python-openid v2.2
++http://openidenabled.com/python-openid/
++
++3. django-authopenid(Included in project already)
++http://code.google.com/p/django-authopenid/
++
++4. html5lib
++http://code.google.com/p/html5lib/
++Used for HTML sanitizer
++
++5. Markdown2
++http://code.google.com/p/python-markdown2/
++
++
++INSTALL STEPS:
++-----------------------------------------------
++1. Copy settings_local.py.dist to settings_local.py and
++update all your settings. Check settings.py and update
++it as well if necessory.
++
++2. Prepare your database by using the same database/account
++configuration from above.
++
++3. Run "python manager.py runserver" to startup django
++development environment.
++
++4. There are some demo scripts under sql_scripts folder,
++including badges and test accounts for CNProg.com. You
++don't need them to run your sample.
+diff -ruN CNPROG/junk mikes/junk
+--- CNPROG/junk 2009-06-22 21:42:52.000000000 -0400
++++ mikes/junk 1969-12-31 19:00:00.000000000 -0500
+@@ -1,7 +0,0 @@
+-/branches/beta2/forum/feed.py r110 line 17:
+-/branches/beta2/forum/feed.py r110 line 20:
+-/branches/beta2/forum/forms.py r110 line 63:
+-/branches/beta2/templates/question.html r120 line 237:
+-/branches/beta2/templates/question.html r120 line 57:
+-/branches/beta2/templates/question.html r120 line 456:
+-/branches/beta2/forum/views.py r127 line 1088:
+diff -ruN CNPROG/lanai.psproj mikes/lanai.psproj
+--- CNPROG/lanai.psproj 2009-06-22 21:42:52.000000000 -0400
++++ mikes/lanai.psproj 1969-12-31 19:00:00.000000000 -0500
+@@ -1,557 +0,0 @@
+-[PyScripter]
+-Version=1.9.9.3
+-
+-[Project]
+-ClassName=TProjectRootNode
+-StoreRelativePaths=FALSE
+-ShowFileExtensions=FALSE
+-
+-[Project\ChildNodes]
+-Count=2
+-
+-[Project\ChildNodes\Node0]
+-ClassName=TProjectFilesNode
+-
+-[Project\ChildNodes\Node0\ChildNodes]
+-Count=1
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0]
+-ClassName=TProjectFolderNode
+-Name=src
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes]
+-Count=10
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0]
+-ClassName=TProjectFolderNode
+-Name=django_authopenid
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes]
+-Count=9
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\django_authopenid\__init__.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\django_authopenid\admin.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\django_authopenid\forms.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\django_authopenid\middleware.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\django_authopenid\mimeparse.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node5]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\django_authopenid\models.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node6]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\django_authopenid\urls.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node7]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\django_authopenid\util.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node8]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\django_authopenid\views.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1]
+-ClassName=TProjectFolderNode
+-Name=forum
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes]
+-Count=12
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0]
+-ClassName=TProjectFolderNode
+-Name=management
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes]
+-Count=2
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0]
+-ClassName=TProjectFolderNode
+-Name=commands
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes]
+-Count=3
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\management\commands\__init__.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\management\commands\mark_offensive_cron.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\management\commands\sample_command.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\management\__init__.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1]
+-ClassName=TProjectFolderNode
+-Name=templatetags
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1\ChildNodes]
+-Count=3
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node0]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\templatetags\__init__.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\templatetags\extra_filters.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\templatetags\extra_tags.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\__init__.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node3]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\admin.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node4]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\auth.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node5]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\const.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node6]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\diff.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node7]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\forms.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node8]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\managers.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node9]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\models.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node10]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\user.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1\ChildNodes\Node11]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\forum\views.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2]
+-ClassName=TProjectFolderNode
+-Name=sql_scripts
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes]
+-Count=6
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node0]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\sql_scripts\cnprog_new_install.sql
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_01_13_001.sql
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_01_13_002.sql
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node3]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_12_24_001.sql
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node4]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_12_27_001.sql
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2\ChildNodes\Node5]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\sql_scripts\update_2009_12_27_002.sql
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3]
+-ClassName=TProjectFolderNode
+-Name=templates
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes]
+-Count=44
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0]
+-ClassName=TProjectFolderNode
+-Name=authopenid
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes]
+-Count=10
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node0]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\changeemail.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\changeopenid.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\changepw.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node3]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\complete.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node4]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\delete.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node5]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\failure.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node6]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\sendpw.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node7]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\settings.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node8]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\signin.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node0\ChildNodes\Node9]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\authopenid\signup.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1]
+-ClassName=TProjectFolderNode
+-Name=content
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes]
+-Count=2
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0]
+-ClassName=TProjectFolderNode
+-Name=js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes]
+-Count=10
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0]
+-ClassName=TProjectFolderNode
+-Name=wmd
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes]
+-Count=3
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node0]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\wmd\showdown.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\wmd\wmd-base.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\wmd\wmd-plus.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\com.cnprog.editor.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\com.cnprog.post.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node3]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\com.cnprog.utils.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node4]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\excanvas.pack.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node5]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\jquery.flot.pack.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node6]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\jquery.openid.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node7]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\jquery.validate.pack.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node8]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\jquery-1.2.6.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node0\ChildNodes\Node9]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\js\jquery-1.2.6.min.js
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1]
+-ClassName=TProjectFolderNode
+-Name=style
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes]
+-Count=4
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node0]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\style\default.css
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\style\jquery.autocomplete.css
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\style\openid.css
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node1\ChildNodes\Node1\ChildNodes\Node3]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\content\style\prettify.css
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\404.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node3]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\500.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node4]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\about.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node5]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\answer_edit.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node6]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\ask.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node7]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\badge.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node8]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\badges.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node9]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\base.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node10]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\base_content.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node11]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\close.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node12]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\faq.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node13]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\footer.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node14]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\header.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node15]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\index.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node16]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\logout.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node17]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\pagesize.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node18]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\paginator.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node19]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\privacy.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node20]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\question.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node21]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\question_edit.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node22]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\question_retag.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node23]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\questions.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node24]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\reopen.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node25]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\revisions_answer.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node26]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\revisions_question.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node27]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\sidebar.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node28]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\tags.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node29]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\unanswered.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node30]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node31]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_edit.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node32]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_favorites.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node33]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_footer.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node34]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_info.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node35]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_preferences.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node36]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_recent.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node37]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_reputation.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node38]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_responses.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node39]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_stats.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node40]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_tabs.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node41]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\user_votes.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node42]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\users.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node3\ChildNodes\Node43]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\templates\users_questions.html
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4]
+-ClassName=TProjectFolderNode
+-Name=utils
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes]
+-Count=4
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes\Node0]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\utils\__init__.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes\Node1]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\utils\cache.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes\Node2]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\utils\html.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node4\ChildNodes\Node3]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\utils\lists.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node5]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\__init__.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node6]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\manage.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node7]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\settings.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node8]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\test.py
+-
+-[Project\ChildNodes\Node0\ChildNodes\Node0\ChildNodes\Node9]
+-ClassName=TProjectFileNode
+-FileName=C:\Projects\Lanai\src\urls.py
+-
+-[Project\ChildNodes\Node1]
+-ClassName=TProjectRunConfiguationsNode
+-
+-[Project\ExtraPythonPath]
+-Count=0
+-
+diff -ruN CNPROG/LICENSE mikes/LICENSE
+--- CNPROG/LICENSE 2009-06-22 21:42:52.000000000 -0400
++++ mikes/LICENSE 2009-07-25 19:09:58.088150984 -0400
+@@ -1,12 +1,14 @@
+-Ȩ(c) 2008 CNProg.com
++Copyright (C) 2009. Chen Gang
+
+-2.0汾Apache֤("֤")Ȩ
+-ݱ֤ûԲʹôļ
+-ûɴַ֤
++This program is free software: you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation, either version 3 of the License, or
++(at your option) any later version.
+
+-http://www.apache.org/licenses/LICENSE-2.0
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
+
+-÷Ҫͬ⣬
+-ַ֤ǻ"ԭ"ṩ
+-κʾĻʾı֤
+-֤£ضԵĹϽȨ޺ơ
+\ No newline at end of file
++You should have received a copy of the GNU General Public License
++along with this program. If not, see <http://www.gnu.org/licenses/>.
+diff -ruN CNPROG/locale/zh_CN/LC_MESSAGES/django.po mikes/locale/zh_CN/LC_MESSAGES/django.po
+--- CNPROG/locale/zh_CN/LC_MESSAGES/django.po 1969-12-31 19:00:00.000000000 -0500
++++ mikes/locale/zh_CN/LC_MESSAGES/django.po 2009-07-25 19:09:58.108151006 -0400
+@@ -0,0 +1,629 @@
++# Chinese translations for CNProg.com
++# Copyright (C) 2009
++# This file is distributed under the same license as the CNPROG package.
++# Mike Chen <chagel@gmail.com>, 2009.
++#
++#, fuzzy
++msgid ""
++msgstr ""
++"Project-Id-Version: PACKAGE VERSION\n"
++"Report-Msgid-Bugs-To: \n"
++"POT-Creation-Date: 2009-07-15 13:53+0000\n"
++"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
++"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
++"Language-Team: LANGUAGE <LL@li.org>\n"
++"MIME-Version: 1.0\n"
++"Content-Type: text/plain; charset=UTF-8\n"
++"Content-Transfer-Encoding: 8bit\n"
++
++#: settings.py:12
++msgid "account/"
++msgstr ""
++
++#: settings.py:12 django_authopenid/urls.py:9 django_authopenid/urls.py:11
++msgid "signin/"
++msgstr ""
++
++#: django_authopenid/forms.py:67 django_authopenid/views.py:93
++msgid "i-names are not supported"
++msgstr "i-names不支持。"
++
++#: django_authopenid/forms.py:102 django_authopenid/forms.py:207
++msgid ""
++"Usernames can only contain letters, numbers and "
++"underscores"
++msgstr "用户名格式有误。只有字母,数字和下划线是允许的。"
++
++#: django_authopenid/forms.py:109
++msgid ""
++"This username does not exist in our database. Please "
++"choose another."
++msgstr "用户名不存在。请重新输入。"
++
++#: django_authopenid/forms.py:126 django_authopenid/forms.py:231
++msgid ""
++"Please enter a valid username and password. Note that "
++"both fields are case-sensitive."
++msgstr "请输入用户名和密码。注意区分大小写。"
++
++#: django_authopenid/forms.py:130 django_authopenid/forms.py:235
++msgid "This account is inactive."
++msgstr "用户已冻结。"
++
++#: django_authopenid/forms.py:184
++msgid ""
++"This email is already registered in our database. Please "
++"choose another."
++msgstr "电子邮件已被注册。请使用一个新的邮件地址。"
++
++#: django_authopenid/forms.py:214
++msgid ""
++"This username don't exist. Please choose another."
++msgstr "用户名不存在"
++
++#: django_authopenid/forms.py:330
++msgid ""
++"Old password is incorrect. Please enter the correct "
++"password."
++msgstr "旧密码错误。"
++
++#: django_authopenid/forms.py:342
++msgid "new passwords do not match"
++msgstr "新密码不匹配"
++
++#: django_authopenid/forms.py:434
++msgid "Incorrect username."
++msgstr "用户名不正确"
++
++#: django_authopenid/urls.py:10
++msgid "signout/"
++msgstr ""
++
++#: django_authopenid/urls.py:11
++msgid "complete/"
++msgstr ""
++
++#: django_authopenid/urls.py:13
++msgid "register/"
++msgstr ""
++
++#: django_authopenid/urls.py:14
++msgid "signup/"
++msgstr ""
++
++#: django_authopenid/urls.py:16
++msgid "sendpw/"
++msgstr ""
++
++#: django_authopenid/urls.py:26
++msgid "delete/"
++msgstr ""
++
++#: django_authopenid/views.py:99
++#, python-format
++msgid "非法OpenID地址: %s"
++msgstr ""
++
++#: django_authopenid/views.py:366 templates/index.html:78
++msgid "Welcome"
++msgstr "欢迎"
++
++#: django_authopenid/views.py:456
++msgid "Password changed."
++msgstr "密码已更新。"
++
++#: django_authopenid/views.py:488
++msgid "Email changed."
++msgstr "邮件地址已更新。"
++
++#: django_authopenid/views.py:519 django_authopenid/views.py:671
++#, python-format
++msgid "No OpenID %s found associated in our database"
++msgstr "该OpenID %s 不在系统中。"
++
++#: django_authopenid/views.py:523 django_authopenid/views.py:678
++#, python-format
++msgid "The OpenID %s isn't associated to current user logged in"
++msgstr "OpenID %s 没有和当前登录用户绑定。"
++
++#: django_authopenid/views.py:531
++msgid "Email Changed."
++msgstr "邮件地址已更新。"
++
++#: django_authopenid/views.py:606
++msgid "This OpenID is already associated with another account."
++msgstr "这个OpenID已经绑定到另外一个帐号。"
++
++#: django_authopenid/views.py:611
++#, python-format
++msgid "OpenID %s is now associated with your account."
++msgstr "OpenID %s 已经绑定到您的帐号。"
++
++#: django_authopenid/views.py:681
++msgid "Account deleted."
++msgstr "帐号已删除。"
++
++#: django_authopenid/views.py:721
++msgid "Request for new password"
++msgstr "找回密码"
++
++#: django_authopenid/views.py:734
++msgid "A new password has been sent to your email address."
++msgstr "新的密码已经发送到您的邮件帐号。"
++
++#: django_authopenid/views.py:764
++#, python-format
++msgid ""
++"Could not change password. Confirmation key '%s' is not "
++"registered."
++msgstr "不能修改密码。确认信息 '%s' 有误。"
++
++#: django_authopenid/views.py:773
++msgid ""
++"Can not change password. User don't exist anymore in our "
++"database."
++msgstr "不能修改密码。用户帐号不存在。"
++
++#: django_authopenid/views.py:782
++#, python-format
++msgid "Password changed for %s. You may now sign in."
++msgstr "帐号 %s 的密码已经修改。您现在可以用它来登录。"
++
++#: forum/user.py:17
++msgid "Overview"
++msgstr "概览"
++
++#: forum/user.py:18
++msgid "User overview"
++msgstr "用户概览"
++
++#: forum/user.py:19
++msgid "Overview - User Profile"
++msgstr "概览-用户资料"
++
++#: forum/user.py:25
++msgid "Recent"
++msgstr "最近活动"
++
++#: forum/user.py:26
++msgid "Recent activities"
++msgstr "用户最近活动情况"
++
++#: forum/user.py:27
++msgid "Recent - User Profile"
++msgstr "最近活动-用户资料"
++
++#: forum/user.py:34
++msgid "Response"
++msgstr "回应"
++
++#: forum/user.py:35
++msgid "Responses from others"
++msgstr "其他用户的回答和评论"
++
++#: forum/user.py:36
++msgid "Response - User Profile"
++msgstr "回应-用户资料"
++
++#: forum/user.py:43
++msgid "Reputation"
++msgstr "积分"
++
++#: forum/user.py:44
++msgid "Community reputation"
++msgstr "社区积分"
++
++#: forum/user.py:45
++msgid "Reputation - User Profile"
++msgstr "积分-用户资料"
++
++#: forum/user.py:51
++msgid "Favorites"
++msgstr "收藏"
++
++#: forum/user.py:52
++msgid "User's favorite questions"
++msgstr "用户收藏的问题"
++
++#: forum/user.py:53
++msgid "Favorites - User Profile"
++msgstr "收藏-用户资料"
++
++#: forum/user.py:60 templates/index.html:46 templates/questions.html:45
++msgid "Votes"
++msgstr "投票"
++
++#: forum/user.py:61
++msgid "Votes history"
++msgstr "用户投票历史"
++
++#: forum/user.py:62
++msgid "Votes - User Profile"
++msgstr "投票-用户资料"
++
++#: forum/user.py:69
++msgid "Preferences"
++msgstr "设置"
++
++#: forum/user.py:70
++msgid "User preferences"
++msgstr "用户参数设置"
++
++#: forum/user.py:71
++msgid "Preferences - User Profile"
++msgstr "设置-用户资料"
++
++#: templates/badges.html:5 templates/badges.html.py:16
++#: templates/header.html:31
++msgid "Badges"
++msgstr "奖牌榜"
++
++#: templates/base.html:53 templates/base_content.html:52
++msgid "Congratulations! You have new badges: "
++msgstr "恭喜您被授予奖牌:"
++
++#: templates/base.html:54 templates/base_content.html:53
++msgid "go to see"
++msgstr "查看"
++
++#: templates/base.html:55 templates/base_content.html:54
++#: templates/header.html:35
++msgid "Profile"
++msgstr "我的资料"
++
++#: templates/footer.html:5 templates/header.html:10 templates/index.html:81
++msgid "About us"
++msgstr "关于我们"
++
++#: templates/footer.html:6 templates/header.html:11
++msgid "faq"
++msgstr "常见问题"
++
++#: templates/footer.html:8
++msgid "Contact"
++msgstr "联系我们"
++
++#: templates/footer.html:9
++msgid "Privacy"
++msgstr "隐私政策"
++
++#: templates/footer.html:10
++msgid "Feedback"
++msgstr "用户反馈"
++
++#: templates/header.html:6 templates/logout.html:5 templates/logout.html.py:16
++msgid "Logout"
++msgstr "退出登录"
++
++#: templates/header.html:8
++msgid "Login"
++msgstr "登录"
++
++#: templates/header.html:21
++msgid "link to homepage"
++msgstr "返回首页"
++
++#: templates/header.html:27 templates/header.html.py:56
++#: templates/index.html:21
++msgid "Questions"
++msgstr "问题"
++
++#: templates/header.html:28 templates/header.html.py:57
++msgid "Tags"
++msgstr "标签"
++
++#: templates/header.html:29 templates/header.html.py:58
++msgid "Users"
++msgstr "用户"
++
++#: templates/header.html:30
++msgid "Books"
++msgstr "读书"
++
++#: templates/header.html:32
++msgid "Unanswered"
++msgstr "没有回答的问题"
++
++#: templates/header.html:38
++msgid "Ask a question"
++msgstr "我要提问"
++
++#: templates/header.html:53
++msgid "Search"
++msgstr "搜索"
++
++#: templates/index.html:6
++msgid "Home"
++msgstr "首页"
++
++#: templates/index.html:23 templates/questions.html:25
++msgid "Newest updated questions"
++msgstr "最新更新的问题"
++
++#: templates/index.html:23 templates/questions.html:24
++msgid "Newest"
++msgstr "最新问题"
++
++#: templates/index.html:24 templates/questions.html:26
++msgid "Questions with most answers"
++msgstr "被回复最多的问题"
++
++#: templates/index.html:24 templates/questions.html:26
++msgid "Hottest"
++msgstr "最热问题"
++
++#: templates/index.html:25 templates/questions.html:27
++msgid "Questions with most votes"
++msgstr "被投票最多的问题"
++
++#: templates/index.html:25 templates/questions.html:27
++msgid "Best"
++msgstr "最有价值问题"
++
++#: templates/index.html:26 templates/index.html.py:118
++#: templates/questions.html:22
++msgid "All questions"
++msgstr "所有问题"
++
++#: templates/index.html:26
++msgid "All"
++msgstr "所有问题"
++
++#: templates/index.html:45 templates/questions.html:44
++msgid "Answers"
++msgstr "回答"
++
++#: templates/index.html:47 templates/questions.html:46
++msgid "Visits"
++msgstr "访问"
++
++#: templates/index.html:55 templates/questions.html:57
++#: templates/questions.html.py:69
++msgid "Community wiki"
++msgstr "社区wiki"
++
++#: templates/index.html:67 templates/index.html.py:91
++#: templates/questions.html:83
++msgid "Browse questions with tag of "
++msgstr "查看所有以下主题问题:"
++
++#: templates/index.html:87
++msgid "Recent tags"
++msgstr "最新标签"
++
++#: templates/index.html:94 templates/index.html.py:118
++msgid "Popular tags"
++msgstr "受欢迎的标签"
++
++#: templates/index.html:98
++msgid "Recent badges"
++msgstr "最新奖牌"
++
++#: templates/index.html:109
++msgid "All badges"
++msgstr "所有奖牌"
++
++#: templates/index.html:113
++msgid "RSS feed of recent 30 questions"
++msgstr "RSS订阅最新30个问题"
++
++#: templates/index.html:113
++msgid "Subscribe"
++msgstr "订阅最新问题"
++
++#: templates/index.html:118
++msgid "Are you looking for more questions? Try to browse"
++msgstr "在寻找更多问题吗?请查阅"
++
++#: templates/index.html:118
++msgid " or "
++msgstr " 或者 "
++
++#: templates/index.html:118
++msgid ". Please help us answer "
++msgstr "。请帮助我们回答"
++
++#: templates/index.html:118
++msgid "Unanswered questions"
++msgstr "没有回答的问题"
++
++#: templates/pagesize.html:5
++msgid "Size per page:"
++msgstr "每页显示:"
++
++#: templates/paginator.html:5
++msgid "Previous"
++msgstr "上一页"
++
++#: templates/questions.html:6
++msgid "Question list"
++msgstr "问题列表"
++
++#: templates/questions.html:22
++msgid "Tagged questions"
++msgstr "标签问题"
++
++#: templates/questions.html:22
++msgid "Query result"
++msgstr "查询结果"
++
++#: templates/questions.html:24
++msgid "New questions"
++msgstr "最新问题"
++
++#: templates/questions.html:25
++msgid "Active"
++msgstr "活跃问题"
++
++#: templates/questions.html:125
++msgid "Related tags"
++msgstr "相关标签"
++
++#: templates/authopenid/changeemail.html:10
++msgid "Account: change email"
++msgstr "修改电子邮件"
++
++#: templates/authopenid/changeemail.html:13
++msgid ""
++"This is where you can change the email address associated with your account. "
++"Please keep this email address up to date so we can send you a password-"
++"reset email if you request one."
++msgstr ""
++"您可以在这里修改您的电子邮件,请确保这个邮件地址有效-找回密码将发送新密码到您"
++"的邮件地址。"
++
++#: templates/authopenid/changeemail.html:15
++#: templates/authopenid/changeopenid.html:13
++#: templates/authopenid/changepw.html:18 templates/authopenid/delete.html:14
++#: templates/authopenid/delete.html:24
++msgid "Please correct errors below:"
++msgstr "请改正以下错误:"
++
++#: templates/authopenid/changeemail.html:32
++msgid "Email"
++msgstr "电子邮件"
++
++#: templates/authopenid/changeemail.html:33
++msgid "Password"
++msgstr "密码"
++
++#: templates/authopenid/changeemail.html:35
++msgid "Change email"
++msgstr "修改电子邮件"
++
++#: templates/authopenid/changeopenid.html:7
++msgid "Account: change OpenID URL"
++msgstr "修改OpenID地址"
++
++#: templates/authopenid/changeopenid.html:11
++msgid ""
++"This is where you can change your OpenID URL. Make sure you remember it!"
++msgstr "请修改您的OpenID地址,请不要忘记这个地址!"
++
++#: templates/authopenid/changeopenid.html:28
++msgid "OpenID URL:"
++msgstr "OpenID地址:"
++
++#: templates/authopenid/changeopenid.html:29
++msgid "Change OpenID"
++msgstr "修改OpenID"
++
++#: templates/authopenid/changepw.html:13
++msgid "Account: change password"
++msgstr "修改密码"
++
++#: templates/authopenid/changepw.html:16
++msgid "This is where you can change your password. Make sure you remember it!"
++msgstr "请修改您的密码,切记不要忘记!"
++
++#: templates/authopenid/changepw.html:26
++msgid "Current password"
++msgstr "旧密码"
++
++#: templates/authopenid/changepw.html:27
++msgid "New password"
++msgstr "新密码"
++
++#: templates/authopenid/changepw.html:28
++msgid "New password again"
++msgstr "重复密码"
++
++#: templates/authopenid/changepw.html:29
++msgid "Change password"
++msgstr "修改密码"
++
++#: templates/authopenid/delete.html:8
++msgid "Account: delete account"
++msgstr "删除帐号"
++
++#: templates/authopenid/delete.html:12
++msgid ""
++"Note: After deleting your account, anyone will be able to register this "
++"username."
++msgstr "注意:删除您的帐号后,任何其他人可以再注册这个帐号。"
++
++#: templates/authopenid/delete.html:16
++msgid "Check confirm box, if you want delete your account."
++msgstr "如果确定删除,请选中多选框。"
++
++#: templates/authopenid/delete.html:19
++msgid "Password:"
++msgstr "密码:"
++
++#: templates/authopenid/delete.html:31
++msgid "I am sure I want to delete my account."
++msgstr "我确认要删除这个帐号。"
++
++#: templates/authopenid/delete.html:32
++msgid "Password/OpenID URL"
++msgstr "密码/OpenID地址"
++
++#: templates/authopenid/delete.html:32
++msgid "(required for your security)"
++msgstr "(必需)"
++
++#: templates/authopenid/delete.html:34
++msgid "Delete account permanently"
++msgstr "永久删除帐号"
++
++#: templates/authopenid/settings.html:29
++msgid "Give your account a new password."
++msgstr "修改密码"
++
++#: templates/authopenid/settings.html:31
++msgid "Add or update the email address associated with your account."
++msgstr "添加或者更新您的邮件地址。"
++
++#: templates/authopenid/settings.html:34
++msgid "Change openid associated to your account"
++msgstr "修改和你帐号绑定的OpenID地址"
++
++#: templates/authopenid/settings.html:38
++msgid "Erase your username and all your data from website"
++msgstr "删除您的帐号和所有内容"
++
++#, fuzzy
++#~ msgid "Badges "
++#~ msgstr "奖牌列表"
++
++#~ msgid ""
++#~ "This username is already taken. Please choose another."
++#~ msgstr "用户名已经被注册,请选用一个新的帐号。"
++
++#~ msgid "Your OpenID is verified! "
++#~ msgstr "您的OpenID帐号已经验证通过"
++
++#~ msgid "Associate your OpenID"
++#~ msgstr "绑定您的OpenID"
++
++#~ msgid ""
++#~ "\n"
++#~ "\t<p>If you're joining <strong>Sitename</strong>, associate your OpenID "
++#~ "with a new account. If you're already a member, associate with your "
++#~ "existing account.</p>\n"
++#~ "\t"
++#~ msgstr ""
++#~ "\n"
++#~ "\t<p>输入您的新帐号或者指定已经存在的帐号。</p>\n"
++#~ "\t"
++
++#~ msgid "A new account"
++#~ msgstr "新帐号"
++
++#~ msgid "An exisiting account"
++#~ msgstr "已经存在的帐号"
++
++#~ msgid "Account: Send a new password"
++#~ msgstr "发送一个新的密码"
++
++#~ msgid ""
++#~ "Lost your password ? Here you can ask to reset your password. Enter the "
++#~ "username you use and you will get a confirmation email with your new "
++#~ "password. This new password will be activated only after you have clicked "
++#~ "on the link in the email."
++#~ msgstr ""
++#~ "丢失了您的密码?你可以在这里重设密码。输入用户名你会收到新的密码的邮件。密"
++#~ "码只有您在激活邮件中的链接才会被激活。"
++
++#~ msgid "Send new password"
++#~ msgstr "发送新密码"
+diff -ruN CNPROG/middleware/pagesize.py mikes/middleware/pagesize.py
+--- CNPROG/middleware/pagesize.py 1969-12-31 19:00:00.000000000 -0500
++++ mikes/middleware/pagesize.py 2009-07-25 19:09:58.108151006 -0400
+@@ -0,0 +1,29 @@
++# used in questions
++QUESTIONS_PAGE_SIZE = 10
++class QuestionsPageSizeMiddleware(object):
++ def process_request(self, request):
++ # Set flag to False by default. If it is equal to True, then need to be saved.
++ pagesize_changed = False
++ # get pagesize from session, if failed then get default value
++ user_page_size = request.session.get("pagesize", QUESTIONS_PAGE_SIZE)
++ # set pagesize equal to logon user specified value in database
++ if request.user.is_authenticated() and request.user.questions_per_page > 0:
++ user_page_size = request.user.questions_per_page
++
++ try:
++ # get new pagesize from UI selection
++ pagesize = int(request.GET.get('pagesize', user_page_size))
++ if pagesize <> user_page_size:
++ pagesize_changed = True
++
++ except ValueError:
++ pagesize = user_page_size
++
++ # save this pagesize to user database
++ if pagesize_changed:
++ if request.user.is_authenticated():
++ user = request.user
++ user.questions_per_page = pagesize
++ user.save()
++ # put pagesize into session
++ request.session["pagesize"] = pagesize
+\ No newline at end of file
+diff -ruN CNPROG/settings_local.py mikes/settings_local.py
+--- CNPROG/settings_local.py 2009-07-25 18:49:15.158341746 -0400
++++ mikes/settings_local.py 1969-12-31 19:00:00.000000000 -0500
+@@ -1,21 +0,0 @@
+-# encoding:utf-8
+-SITE_SRC_ROOT = '/change_me/'
+-
+-#for logging
+-import logging
+-LOG_FILENAME = SITE_SRC_ROOT + 'django.lanai.log'
+-logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
+-
+-DATABASE_NAME = 'cnprog' # Or path to database file if using sqlite3.
+-DATABASE_USER = 'root' # Not used with sqlite3.
+-DATABASE_PASSWORD = '' # Not used with sqlite3.
+-
+-MIDDLEWARE_CLASSES = (
+- 'django.middleware.gzip.GZipMiddleware',
+- 'django.contrib.sessions.middleware.SessionMiddleware',
+- 'django.middleware.locale.LocaleMiddleware',
+- 'django.middleware.common.CommonMiddleware',
+- 'django.contrib.auth.middleware.AuthenticationMiddleware',
+- 'django.middleware.transaction.TransactionMiddleware',
+- #'debug_toolbar.middleware.DebugToolbarMiddleware',
+-)
+diff -ruN CNPROG/settings_local.py.dist mikes/settings_local.py.dist
+--- CNPROG/settings_local.py.dist 1969-12-31 19:00:00.000000000 -0500
++++ mikes/settings_local.py.dist 2009-07-25 19:09:58.108151006 -0400
+@@ -0,0 +1,25 @@
++SITE_SRC_ROOT = '/Users/sailing/Development/cnprog_beta2'
++
++#for logging
++import logging
++LOG_FILENAME = '/Users/sailing/Development/cnprog_beta2/django.lanai.log'
++logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
++
++
++#Database configuration
++DATABASE_ENGINE = 'mysql'
++DATABASE_HOST = ''
++DATABASE_PORT = ''
++DATABASE_NAME = 'cnprog' # Or path to database file if using sqlite3.
++DATABASE_USER = 'root' # Not used with sqlite3.
++DATABASE_PASSWORD = '' # Not used with sqlite3.
++
++
++# Absolute path to the directory that holds media.
++# Example: "/home/media/media.lawrence.com/"
++MEDIA_ROOT = '/Users/sailing/Development/cnprog_beta2/templates/upfiles/'
++
++# URL that handles the media served from MEDIA_ROOT. Make sure to use a
++# trailing slash if there is a path component (optional in other cases).
++# Examples: "http://media.lawrence.com", "http://example.com/media/"
++MEDIA_URL = 'http://127.0.0.1:8000/upfiles/'
+diff -ruN CNPROG/settings.py mikes/settings.py
+--- CNPROG/settings.py 2009-07-25 18:49:15.158341746 -0400
++++ mikes/settings.py 2009-07-25 19:09:58.108151006 -0400
+@@ -1,51 +1,24 @@
++# encoding:utf-8
+ # Django settings for lanai project.
+ import os.path
+
++#DEBUG SETTINGS
+ DEBUG = True
+ TEMPLATE_DEBUG = DEBUG
+-
+-
+-#David Cramer debug toolbar
+ INTERNAL_IPS = ('127.0.0.1',)
+-DEBUG_TOOLBAR_PANELS = (
+- 'debug_toolbar.panels.sql.SQLDebugPanel',
+- 'debug_toolbar.panels.headers.HeaderDebugPanel',
+- 'debug_toolbar.panels.cache.CacheDebugPanel',
+- 'debug_toolbar.panels.profiler.ProfilerDebugPanel',
+- 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel',
+- 'debug_toolbar.panels.templates.TemplatesDebugPanel',
+- # If you are using the profiler panel you don't need the timer
+- # 'debug_toolbar.panels.timer.TimerDebugPanel',
+-)
+-
+-DEBUG_TOOLBAR_CONFIG = {
+- "INTERCEPT_REDIRECTS":False
+-}
+
+ #for OpenID auth
+ ugettext = lambda s: s
+ LOGIN_URL = '/%s%s' % (ugettext('account/'), ugettext('signin/'))
+
+-#system will send admins email about error stacktrace if DEBUG=False
++#EMAIL AND ADMINS
+ ADMINS = (
+- ('you', 'you@where.com'),
++ ('CNProg team', 'team@cnprog.com'),
+ )
+-
+ MANAGERS = ADMINS
+
+-DATABASE_ENGINE = 'mysql' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+-#DATABASE_NAME = 'cnprog' # Or path to database file if using sqlite3.
+-#DATABASE_USER = 'root' # Not used with sqlite3.
+-#DATABASE_PASSWORD = '' # Not used with sqlite3.
+-DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
+-DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
+-
+-DATABASE_NAME = 'dbname' # Or path to database file if using sqlite3.
+-DATABASE_USER = 'dbuser' # Not used with sqlite3.
+-DATABASE_PASSWORD = 'dbpass' # Not used with sqlite3.
+-
+-SERVER_EMAIL = 'server@where.com'
+-DEFAULT_FROM_EMAIL = 'from@where.com'
++SERVER_EMAIL = 'webmaster@cnprog.com'
++DEFAULT_FROM_EMAIL = 'webmaster@cnprog.com'
+ EMAIL_HOST_USER = ''
+ EMAIL_HOST_PASSWORD = ''
+ EMAIL_SUBJECT_PREFIX = '[cnprog.com]'
+@@ -53,44 +26,21 @@
+ EMAIL_PORT='587'
+ EMAIL_USE_TLS=True
+
+-
+-
+-
+-# Local time zone for this installation. Choices can be found here:
+-# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+-# although not all choices may be available on all operating systems.
+-# If running in a Windows environment this must be set to the same as your
+-# system time zone.
+-TIME_ZONE = 'America/Chicago'
+-
+-# Language code for this installation. All choices can be found here:
+-# http://www.i18nguy.com/unicode/language-identifiers.html
+-#LANGUAGE_CODE = 'en'
++#LOCALIZATIONS
++TIME_ZONE = 'Asia/Chongqing Asia/Chungking'
++# LANGUAGE_CODE = 'en-us'
+ LANGUAGE_CODE = 'zh-cn'
+-
+ SITE_ID = 1
+-
+-# If you set this to False, Django will make some optimizations so as not
+-# to load the internationalization machinery.
+ USE_I18N = True
+
+-# Absolute path to the directory that holds media.
+-# Example: "/home/media/media.lawrence.com/"
+-MEDIA_ROOT = '/var/www/vhosts/cnprog/templates/upfiles/'
+-
+-# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+-# trailing slash if there is a path component (optional in other cases).
+-# Examples: "http://media.lawrence.com", "http://example.com/media/"
+-MEDIA_URL = 'http://where.com/upfiles/'
+-
+-# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+-# trailing slash.
+-# Examples: "http://foo.com/media/", "/media/".
++#OTHER SETTINS
++APP_TITLE = u'CNProg.com 程序员问答社区'
++APP_URL = 'http://www.cnprog.com'
++APP_KEYWORDS = u'技术问答社区,中国程序员,编程技术社区,程序员社区,程序员论坛,程序员wiki,程序员博客'
++APP_DESCRIPTION = u'中国程序员的编程技术问答社区。我们做专业的、可协作编辑的技术问答社区。'
++APP_INTRO = u' <p>CNProg是一个<strong>面向程序员</strong>的可协作编辑的<strong>开放源代码问答社区</strong>。</p><p> 您可以在这里提问各类<strong>程序技术问题</strong> - 问题不分语言和平台。 同时也希望您对力所能及的问题,给予您的宝贵答案。</p>'
+ ADMIN_MEDIA_PREFIX = '/admin/media/'
+-
+-# Make this unique, and don't share it with anybody.
+-SECRET_KEY = '$oo^&_m&qwbib=ffljk_4m_n*zn-d=g#s0he5fx9xonnym#8p6yigm'
+-
++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 = (
+ 'django.template.loaders.filesystem.load_template_source',
+@@ -105,12 +55,15 @@
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.middleware.transaction.TransactionMiddleware',
+- 'debug_toolbar.middleware.DebugToolbarMiddleware',
++ #'django.middleware.sqlprint.SqlPrintingMiddleware',
++ 'middleware.pagesize.QuestionsPageSizeMiddleware',
++ #'debug_toolbar.middleware.DebugToolbarMiddleware',
+ )
+
+ TEMPLATE_CONTEXT_PROCESSORS = (
+ 'django.core.context_processors.request',
+ 'django.core.context_processors.auth',
++ 'context.application_settings'
+ )
+
+ ROOT_URLCONF = 'urls'
+@@ -119,6 +72,7 @@
+ os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
+ )
+
++#UPLOAD SETTINGS
+ FILE_UPLOAD_TEMP_DIR = os.path.join(os.path.dirname(__file__), 'tmp').replace('\\','/')
+ FILE_UPLOAD_HANDLERS = ("django.core.files.uploadhandler.MemoryFileUploadHandler",
+ "django.core.files.uploadhandler.TemporaryFileUploadHandler",)
+@@ -139,6 +93,7 @@
+ 'django_authopenid',
+ 'debug_toolbar' ,
+ )
+-#local configs
+-from settings_local import *
+-
++
++# User settings
++from settings_local import *
++
+diff -ruN CNPROG/templates/allfiles mikes/templates/allfiles
+--- CNPROG/templates/allfiles 2009-06-22 21:42:52.000000000 -0400
++++ mikes/templates/allfiles 1969-12-31 19:00:00.000000000 -0500
+@@ -1,30 +0,0 @@
+-404.html
+-500.html
+-about.html
+-ask.html
+-badges.html
+-base_content.html
+-base.html
+-book.html
+-close.html
+-faq.html
+-footer.html
+-header.html
+-index.html
+-logout.html
+-pagesize.html
+-paginator.html
+-privacy.html
+-question_edit_tips.html
+-question.html
+-questions.html
+-revisions_answer.html
+-tags.html
+-unanswered.html
+-user_edit.html
+-user_info.html
+-users.html
+-users_questions.html
+-user_stats.html
+-user_tabs.html
+-user_votes.html
+diff -ruN CNPROG/templates/authopenid/htmlfiles mikes/templates/authopenid/htmlfiles
+--- CNPROG/templates/authopenid/htmlfiles 2009-06-22 21:42:52.000000000 -0400
++++ mikes/templates/authopenid/htmlfiles 1969-12-31 19:00:00.000000000 -0500
+@@ -1,8 +0,0 @@
+-changeemail.html
+-changeopenid.html
+-changepw.html
+-delete.html
+-failure.html
+-sendpw.html
+-settings.html
+-signup.html
+diff -ruN CNPROG/templates/base_content.html mikes/templates/base_content.html
+--- CNPROG/templates/base_content.html 2009-06-22 21:49:26.000000000 -0400
++++ mikes/templates/base_content.html 2009-07-25 19:09:58.118151716 -0400
+@@ -1,9 +1,8 @@
++{% load i18n %}
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+-<!-- template base_content.html -->
+-{% load i18n %}
+ <html>
+ <head>
+- <title>{% block title %}{% endblock %} - {% trans "site title" %} - {% trans "site slogan" %}</title>
++ <title>{% block title %}{% endblock %} - {{ APP_TITLE }}</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="verify-v1" content="55uGNnQVJW8p1bbXeF/Xbh9I7nZBM/wLhRz6N/I1kkA=" />
+ <link rel="shortcut icon" href="/content/images/favicon.ico" >
+@@ -83,4 +74,3 @@
+ {% endblock %}
+ </body>
+ </html>
+-<!-- end template base_content.html -->
+diff -ruN CNPROG/templates/base.html mikes/templates/base.html
+--- CNPROG/templates/base.html 2009-06-22 21:49:58.000000000 -0400
++++ mikes/templates/base.html 2009-07-25 19:09:58.118151716 -0400
+@@ -48,6 +40,7 @@
+ notify.show();
+ });
+ </script>
++
+ {% endif %}
+ {% endwith %}
+
+@@ -88,4 +81,3 @@
+ {% endblock %}
+ </body>
+ </html>
+-<!-- end template base.html -->
+diff -ruN CNPROG/templates/content/js/com.cnprog.post.js mikes/templates/content/js/com.cnprog.post.js
+--- CNPROG/templates/content/js/com.cnprog.post.js 2009-06-22 21:42:51.000000000 -0400
++++ mikes/templates/content/js/com.cnprog.post.js 2009-07-25 19:09:58.138152577 -0400
+@@ -613,4 +570,4 @@
+ Prettify
+ http://www.apache.org/licenses/LICENSE-2.0
+ */
+-var PR_SHOULD_USE_CONTINUATION = true; var PR_TAB_WIDTH = 8; var PR_normalizedHtml; var PR; var prettyPrintOne; var prettyPrint; function _pr_isIE6() { var isIE6 = navigator && navigator.userAgent && /\bMSIE 6\./.test(navigator.userAgent); _pr_isIE6 = function() { return isIE6; }; return isIE6; } (function() { function wordSet(words) { words = words.split(/ /g); var set = {}; for (var i = words.length; --i >= 0; ) { var w = words[i]; if (w) { set[w] = null; } } return set; } var FLOW_CONTROL_KEYWORDS = "break continue do else for if return while "; var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " + "double enum extern float goto int long register short signed sizeof " + "static struct switch typedef union unsigned void volatile "; var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " + "new operator private protected public this throw true try "; var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " + "concept concept_map const_cast constexpr decltype " + "dynamic_cast explicit export friend inline late_check " + "mutable namespace nullptr reinterpret_cast static_assert static_cast " + "template typeid typename typeof using virtual wchar_t where "; var JAVA_KEYWORDS = COMMON_KEYWORDS + "boolean byte extends final finally implements import instanceof null " + "native package strictfp super synchronized throws transient "; var CSHARP_KEYWORDS = JAVA_KEYWORDS + "as base by checked decimal delegate descending event " + "fixed foreach from group implicit in interface internal into is lock " + "object out override orderby params readonly ref sbyte sealed " + "stackalloc string select uint ulong unchecked unsafe ushort var "; var JSCRIPT_KEYWORDS = COMMON_KEYWORDS + "debugger eval export function get null set undefined var with " + "Infinity NaN "; var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " + "goto if import last local my next no our print package redo require " + "sub undef unless until use wantarray while BEGIN END "; var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " + "elif except exec finally from global import in is lambda " + "nonlocal not or pass print raise try with yield " + "False True None "; var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" + " defined elsif end ensure false in module next nil not or redo rescue " + "retry self super then true undef unless until when yield BEGIN END "; var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " + "function in local set then until "; var ALL_KEYWORDS = (CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS + PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS); var PR_STRING = 'str'; var PR_KEYWORD = 'kwd'; var PR_COMMENT = 'com'; var PR_TYPE = 'typ'; var PR_LITERAL = 'lit'; var PR_PUNCTUATION = 'pun'; var PR_PLAIN = 'pln'; var PR_TAG = 'tag'; var PR_DECLARATION = 'dec'; var PR_SOURCE = 'src'; var PR_ATTRIB_NAME = 'atn'; var PR_ATTRIB_VALUE = 'atv'; var PR_NOCODE = 'nocode'; function isWordChar(ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); } function spliceArrayInto(inserted, container, containerPosition, countReplaced) { inserted.unshift(containerPosition, countReplaced || 0); try { container.splice.apply(container, inserted); } finally { inserted.splice(0, 2); } } var REGEXP_PRECEDER_PATTERN = function() { var preceders = ["!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=", "&=", "(", "*", "*=", "+=", ",", "-=", "->", "/", "/=", ":", "::", ";", "<", "<<", "<<=", "<=", "=", "==", "===", ">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", "^", "^=", "^^", "^^=", "{", "|", "|=", "||", "||=", "~", "break", "case", "continue", "delete", "do", "else", "finally", "instanceof", "return", "throw", "try", "typeof"]; var pattern = '(?:' + '(?:(?:^|[^0-9.])\\.{1,3})|' + '(?:(?:^|[^\\+])\\+)|' + '(?:(?:^|[^\\-])-)'; for (var i = 0; i < preceders.length; ++i) { var preceder = preceders[i]; if (isWordChar(preceder.charAt(0))) { pattern += '|\\b' + preceder; } else { pattern += '|' + preceder.replace(/([^=<>:&])/g, '\\$1'); } } pattern += '|^)\\s*$'; return new RegExp(pattern); } (); var pr_amp = /&/g; var pr_lt = /</g; var pr_gt = />/g; var pr_quot = /\"/g; function attribToHtml(str) { return str.replace(pr_amp, '&amp;').replace(pr_lt, '&lt;').replace(pr_gt, '&gt;').replace(pr_quot, '&quot;'); } function textToHtml(str) { return str.replace(pr_amp, '&amp;').replace(pr_lt, '&lt;').replace(pr_gt, '&gt;'); } var pr_ltEnt = /&lt;/g; var pr_gtEnt = /&gt;/g; var pr_aposEnt = /&apos;/g; var pr_quotEnt = /&quot;/g; var pr_ampEnt = /&amp;/g; var pr_nbspEnt = /&nbsp;/g; function htmlToText(html) { var pos = html.indexOf('&'); if (pos < 0) { return html; } for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0; ) { var end = html.indexOf(';', pos); if (end >= 0) { var num = html.substring(pos + 3, end); var radix = 10; if (num && num.charAt(0) === 'x') { num = num.substring(1); radix = 16; } var codePoint = parseInt(num, radix); if (!isNaN(codePoint)) { html = (html.substring(0, pos) + String.fromCharCode(codePoint) + html.substring(end + 1)); } } } return html.replace(pr_ltEnt, '<').replace(pr_gtEnt, '>').replace(pr_aposEnt, "'").replace(pr_quotEnt, '"').replace(pr_ampEnt, '&').replace(pr_nbspEnt, ' '); } function isRawContent(node) { return 'XMP' === node.tagName; } function normalizedHtml(node, out) { switch (node.nodeType) { case 1: var name = node.tagName.toLowerCase(); out.push('<', name); for (var i = 0; i < node.attributes.length; ++i) { var attr = node.attributes[i]; if (!attr.specified) { continue; } out.push(' '); normalizedHtml(attr, out); } out.push('>'); for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } if (node.firstChild || !/^(?:br|link|img)$/.test(name)) { out.push('<\/', name, '>'); } break; case 2: out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"'); break; case 3: case 4: out.push(textToHtml(node.nodeValue)); break; } } var PR_innerHtmlWorks = null; function getInnerHtml(node) { if (null === PR_innerHtmlWorks) { var testNode = document.createElement('PRE'); testNode.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />')); PR_innerHtmlWorks = !/</.test(testNode.innerHTML); } if (PR_innerHtmlWorks) { var content = node.innerHTML; if (isRawContent(node)) { content = textToHtml(content); } return content; } var out = []; for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } return out.join(''); } function makeTabExpander(tabWidth) { var SPACES = ' '; var charInLine = 0; return function(plainText) { var out = null; var pos = 0; for (var i = 0, n = plainText.length; i < n; ++i) { var ch = plainText.charAt(i); switch (ch) { case '\t': if (!out) { out = []; } out.push(plainText.substring(pos, i)); var nSpaces = tabWidth - (charInLine % tabWidth); charInLine += nSpaces; for (; nSpaces >= 0; nSpaces -= SPACES.length) { out.push(SPACES.substring(0, nSpaces)); } pos = i + 1; break; case '\n': charInLine = 0; break; default: ++charInLine; } } if (!out) { return plainText; } out.push(plainText.substring(pos)); return out.join(''); }; } var pr_chunkPattern = /(?:[^<]+|<!--[\s\S]*?-->|<!\[CDATA\[([\s\S]*?)\]\]>|<\/?[a-zA-Z][^>]*>|<)/g; var pr_commentPrefix = /^<!--/; var pr_cdataPrefix = /^<\[CDATA\[/; var pr_brPrefix = /^<br\b/i; var pr_tagNameRe = /^<(\/?)([a-zA-Z]+)/; function extractTags(s) { var matches = s.match(pr_chunkPattern); var sourceBuf = []; var sourceBufLen = 0; var extractedTags = []; if (matches) { for (var i = 0, n = matches.length; i < n; ++i) { var match = matches[i]; if (match.length > 1 && match.charAt(0) === '<') { if (pr_commentPrefix.test(match)) { continue; } if (pr_cdataPrefix.test(match)) { sourceBuf.push(match.substring(9, match.length - 3)); sourceBufLen += match.length - 12; } else if (pr_brPrefix.test(match)) { sourceBuf.push('\n'); ++sourceBufLen; } else { if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) { var name = match.match(pr_tagNameRe)[2]; var depth = 1; end_tag_loop: for (var j = i + 1; j < n; ++j) { var name2 = matches[j].match(pr_tagNameRe); if (name2 && name2[2] === name) { if (name2[1] === '/') { if (--depth === 0) { break end_tag_loop; } } else { ++depth; } } } if (j < n) { extractedTags.push(sourceBufLen, matches.slice(i, j + 1).join('')); i = j; } else { extractedTags.push(sourceBufLen, match); } } else { extractedTags.push(sourceBufLen, match); } } } else { var literalText = htmlToText(match); sourceBuf.push(literalText); sourceBufLen += literalText.length; } } } return { source: sourceBuf.join(''), tags: extractedTags }; } function isNoCodeTag(tag) { return !!tag.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g, ' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/); } function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) { var shortcuts = {}; (function() { var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns); for (var i = allPatterns.length; --i >= 0; ) { var patternParts = allPatterns[i]; var shortcutChars = patternParts[3]; if (shortcutChars) { for (var c = shortcutChars.length; --c >= 0; ) { shortcuts[shortcutChars.charAt(c)] = patternParts; } } } })(); var nPatterns = fallthroughStylePatterns.length; var notWs = /\S/; return function(sourceCode, opt_basePos) { opt_basePos = opt_basePos || 0; var decorations = [opt_basePos, PR_PLAIN]; var lastToken = ''; var pos = 0; var tail = sourceCode; while (tail.length) { var style; var token = null; var match; var patternParts = shortcuts[tail.charAt(0)]; if (patternParts) { match = tail.match(patternParts[1]); token = match[0]; style = patternParts[0]; } else { for (var i = 0; i < nPatterns; ++i) { patternParts = fallthroughStylePatterns[i]; var contextPattern = patternParts[2]; if (contextPattern && !contextPattern.test(lastToken)) { continue; } match = tail.match(patternParts[1]); if (match) { token = match[0]; style = patternParts[0]; break; } } if (!token) { style = PR_PLAIN; token = tail.substring(0, 1); } } decorations.push(opt_basePos + pos, style); pos += token.length; tail = tail.substring(token.length); if (style !== PR_COMMENT && notWs.test(token)) { lastToken = token; } } return decorations; }; } var PR_MARKUP_LEXER = createSimpleLexer([], [[PR_PLAIN, /^[^<]+/, null], [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/, null], [PR_COMMENT, /^<!--[\s\S]*?(?:-->|$)/, null], [PR_SOURCE, /^<\?[\s\S]*?(?:\?>|$)/, null], [PR_SOURCE, /^<%[\s\S]*?(?:%>|$)/, null], [PR_SOURCE, /^<(script|style|xmp)\b[^>]*>[\s\S]*?<\/\1\b[^>]*>/i, null], [PR_TAG, /^<\/?\w[^<>]*>/, null]]); var PR_SOURCE_CHUNK_PARTS = /^(<[^>]*>)([\s\S]*)(<\/[^>]*>)$/; function tokenizeMarkup(source) { var decorations = PR_MARKUP_LEXER(source); for (var i = 0; i < decorations.length; i += 2) { if (decorations[i + 1] === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var sourceChunk = source.substring(start, end); var match = sourceChunk.match(PR_SOURCE_CHUNK_PARTS); if (match) { decorations.splice(i, 2, start, PR_TAG, start + match[1].length, PR_SOURCE, start + match[1].length + (match[2] || '').length, PR_TAG); } } } return decorations; } var PR_TAG_LEXER = createSimpleLexer([[PR_ATTRIB_VALUE, /^\'[^\']*(?:\'|$)/, null, "'"], [PR_ATTRIB_VALUE, /^\"[^\"]*(?:\"|$)/, null, '"'], [PR_PUNCTUATION, /^[<>\/=]+/, null, '<>/=']], [[PR_TAG, /^[\w:\-]+/, /^</], [PR_ATTRIB_VALUE, /^[\w\-]+/, /^=/], [PR_ATTRIB_NAME, /^[\w:\-]+/, null], [PR_PLAIN, /^\s+/, null, ' \t\r\n']]); function splitTagAttributes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_TAG) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var chunk = source.substring(start, end); var subDecorations = PR_TAG_LEXER(chunk, start); spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function sourceDecorator(options) { var shortcutStylePatterns = [], fallthroughStylePatterns = []; if (options.tripleQuotedStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, null, '\'"']); } else if (options.multiLineStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, null, '\'"`']); } else { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, null, '"\'']); } fallthroughStylePatterns.push([PR_PLAIN, /^(?:[^\'\"\`\/\#]+)/, null, ' \r\n']); if (options.hashComments) { shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']); } if (options.cStyleComments) { fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]); fallthroughStylePatterns.push([PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); } if (options.regexLiterals) { var REGEX_LITERAL = ('^/(?=[^/*])' + '(?:[^/\\x5B\\x5C]' + '|\\x5C[\\s\\S]' + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+' + '(?:/|$)'); fallthroughStylePatterns.push([PR_STRING, new RegExp(REGEX_LITERAL), REGEXP_PRECEDER_PATTERN]); } var keywords = wordSet(options.keywords); options = null; var splitStringAndCommentTokens = createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns); var styleLiteralIdentifierPuncRecognizer = createSimpleLexer([], [[PR_PLAIN, /^\s+/, null, ' \r\n'], [PR_PLAIN, /^[a-z_$@][a-z_$@0-9]*/i, null], [PR_LITERAL, /^0x[a-f0-9]+[a-z]/i, null], [PR_LITERAL, /^(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?[a-z]*/i, null, '123456789'], [PR_PUNCTUATION, /^[^\s\w\.$@]+/, null]]); function splitNonStringNonCommentTokens(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_PLAIN) { var start, end, chunk, subDecs; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; chunk = source.substring(start, end); subDecs = styleLiteralIdentifierPuncRecognizer(chunk, start); for (var j = 0, m = subDecs.length; j < m; j += 2) { var subStyle = subDecs[j + 1]; if (subStyle === PR_PLAIN) { var subStart = subDecs[j]; var subEnd = j + 2 < m ? subDecs[j + 2] : chunk.length; var token = source.substring(subStart, subEnd); if (token === '.') { subDecs[j + 1] = PR_PUNCTUATION; } else if (token in keywords) { subDecs[j + 1] = PR_KEYWORD; } else if (/^@?[A-Z][A-Z$]*[a-z][A-Za-z$]*$/.test(token)) { subDecs[j + 1] = token.charAt(0) === '@' ? PR_LITERAL : PR_TYPE; } } } spliceArrayInto(subDecs, decorations, i, 2); i += subDecs.length - 2; } } return decorations; } return function(sourceCode) { var decorations = splitStringAndCommentTokens(sourceCode); decorations = splitNonStringNonCommentTokens(sourceCode, decorations); return decorations; }; } var decorateSource = sourceDecorator({ keywords: ALL_KEYWORDS, hashComments: true, cStyleComments: true, multiLineStrings: true, regexLiterals: true }); function splitSourceNodes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var subDecorations = decorateSource(source.substring(start, end)); for (var j = 0, m = subDecorations.length; j < m; j += 2) { subDecorations[j] += start; } spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function splitSourceAttributes(source, decorations) { var nextValueIsSource = false; for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; var start, end; if (style === PR_ATTRIB_NAME) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; nextValueIsSource = /^on|^style$/i.test(source.substring(start, end)); } else if (style === PR_ATTRIB_VALUE) { if (nextValueIsSource) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var attribValue = source.substring(start, end); var attribLen = attribValue.length; var quoted = (attribLen >= 2 && /^[\"\']/.test(attribValue) && attribValue.charAt(0) === attribValue.charAt(attribLen - 1)); var attribSource; var attribSourceStart; var attribSourceEnd; if (quoted) { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue; } else { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue.substring(1, attribValue.length - 1); } var attribSourceDecorations = decorateSource(attribSource); for (var j = 0, m = attribSourceDecorations.length; j < m; j += 2) { attribSourceDecorations[j] += attribSourceStart; } if (quoted) { attribSourceDecorations.push(attribSourceEnd, PR_ATTRIB_VALUE); spliceArrayInto(attribSourceDecorations, decorations, i + 2, 0); } else { spliceArrayInto(attribSourceDecorations, decorations, i, 2); } } nextValueIsSource = false; } } return decorations; } function decorateMarkup(sourceCode) { var decorations = tokenizeMarkup(sourceCode); decorations = splitTagAttributes(sourceCode, decorations); decorations = splitSourceNodes(sourceCode, decorations); decorations = splitSourceAttributes(sourceCode, decorations); return decorations; } function recombineTagsAndDecorations(sourceText, extractedTags, decorations) { var html = []; var outputIdx = 0; var openDecoration = null; var currentDecoration = null; var tagPos = 0; var decPos = 0; var tabExpander = makeTabExpander(PR_TAB_WIDTH); var adjacentSpaceRe = /([\r\n ]) /g; var startOrSpaceRe = /(^| ) /gm; var newlineRe = /\r\n?|\n/g; var trailingSpaceRe = /[ \r\n]$/; var lastWasSpace = true; function emitTextUpTo(sourceIdx) { if (sourceIdx > outputIdx) { if (openDecoration && openDecoration !== currentDecoration) { html.push('</span>'); openDecoration = null; } if (!openDecoration && currentDecoration) { openDecoration = currentDecoration; html.push('<span class="', openDecoration, '">'); } var htmlChunk = textToHtml(tabExpander(sourceText.substring(outputIdx, sourceIdx))).replace(lastWasSpace ? startOrSpaceRe : adjacentSpaceRe, '$1&nbsp;'); lastWasSpace = trailingSpaceRe.test(htmlChunk); html.push(htmlChunk.replace(newlineRe, '<br />')); outputIdx = sourceIdx; } } while (true) { var outputTag; if (tagPos < extractedTags.length) { if (decPos < decorations.length) { outputTag = extractedTags[tagPos] <= decorations[decPos]; } else { outputTag = true; } } else { outputTag = false; } if (outputTag) { emitTextUpTo(extractedTags[tagPos]); if (openDecoration) { html.push('</span>'); openDecoration = null; } html.push(extractedTags[tagPos + 1]); tagPos += 2; } else if (decPos < decorations.length) { emitTextUpTo(decorations[decPos]); currentDecoration = decorations[decPos + 1]; decPos += 2; } else { break; } } emitTextUpTo(sourceText.length); if (openDecoration) { html.push('</span>'); } return html.join(''); } var langHandlerRegistry = {}; function registerLangHandler(handler, fileExtensions) { for (var i = fileExtensions.length; --i >= 0; ) { var ext = fileExtensions[i]; if (!langHandlerRegistry.hasOwnProperty(ext)) { langHandlerRegistry[ext] = handler; } else if ('console' in window) { console.log('cannot override language handler %s', ext); } } } registerLangHandler(decorateSource, ['default-code']); registerLangHandler(decorateMarkup, ['default-markup', 'html', 'htm', 'xhtml', 'xml', 'xsl']); registerLangHandler(sourceDecorator({ keywords: CPP_KEYWORDS, hashComments: true, cStyleComments: true }), ['c', 'cc', 'cpp', 'cs', 'cxx', 'cyc']); registerLangHandler(sourceDecorator({ keywords: JAVA_KEYWORDS, cStyleComments: true }), ['java']); registerLangHandler(sourceDecorator({ keywords: SH_KEYWORDS, hashComments: true, multiLineStrings: true }), ['bsh', 'csh', 'sh']); registerLangHandler(sourceDecorator({ keywords: PYTHON_KEYWORDS, hashComments: true, multiLineStrings: true, tripleQuotedStrings: true }), ['cv', 'py']); registerLangHandler(sourceDecorator({ keywords: PERL_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['perl', 'pl', 'pm']); registerLangHandler(sourceDecorator({ keywords: RUBY_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['rb']); registerLangHandler(sourceDecorator({ keywords: JSCRIPT_KEYWORDS, cStyleComments: true, regexLiterals: true }), ['js']); function prettyPrintOne(sourceCodeHtml, opt_langExtension) { try { var sourceAndExtractedTags = extractTags(sourceCodeHtml); var source = sourceAndExtractedTags.source; var extractedTags = sourceAndExtractedTags.tags; if (!langHandlerRegistry.hasOwnProperty(opt_langExtension)) { opt_langExtension = /^\s*</.test(source) ? 'default-markup' : 'default-code'; } var decorations = langHandlerRegistry[opt_langExtension].call({}, source); return recombineTagsAndDecorations(source, extractedTags, decorations); } catch (e) { if ('console' in window) { console.log(e); console.trace(); } return sourceCodeHtml; } } function prettyPrint(opt_whenDone) { var isIE6 = _pr_isIE6(); var codeSegments = [document.getElementsByTagName('pre'), document.getElementsByTagName('code'), document.getElementsByTagName('xmp')]; var elements = []; for (var i = 0; i < codeSegments.length; ++i) { for (var j = 0; j < codeSegments[i].length; ++j) { elements.push(codeSegments[i][j]); } } codeSegments = null; var k = 0; function doWork() { var endTime = (PR_SHOULD_USE_CONTINUATION ? new Date().getTime() + 250 : Infinity); for (; k < elements.length && new Date().getTime() < endTime; k++) { var cs = elements[k]; if (cs.className && cs.className.indexOf('prettyprint') >= 0) { var langExtension = cs.className.match(/\blang-(\w+)\b/); if (langExtension) { langExtension = langExtension[1]; } var nested = false; for (var p = cs.parentNode; p; p = p.parentNode) { if ((p.tagName === 'pre' || p.tagName === 'code' || p.tagName === 'xmp') && p.className && p.className.indexOf('prettyprint') >= 0) { nested = true; break; } } if (!nested) { var content = getInnerHtml(cs); content = content.replace(/(?:\r\n?|\n)$/, ''); var newContent = prettyPrintOne(content, langExtension); if (!isRawContent(cs)) { cs.innerHTML = newContent; } else { var pre = document.createElement('PRE'); for (var i = 0; i < cs.attributes.length; ++i) { var a = cs.attributes[i]; if (a.specified) { var aname = a.name.toLowerCase(); if (aname === 'class') { pre.className = a.value; } else { pre.setAttribute(a.name, a.value); } } } pre.innerHTML = newContent; cs.parentNode.replaceChild(pre, cs); cs = pre; } if (isIE6 && cs.tagName === 'PRE') { var lineBreaks = cs.getElementsByTagName('br'); for (var j = lineBreaks.length; --j >= 0; ) { var lineBreak = lineBreaks[j]; lineBreak.parentNode.replaceChild(document.createTextNode('\r\n'), lineBreak); } } } } } if (k < elements.length) { setTimeout(doWork, 250); } else if (opt_whenDone) { opt_whenDone(); } } doWork(); } window['PR_normalizedHtml'] = normalizedHtml; window['prettyPrintOne'] = prettyPrintOne; window['prettyPrint'] = prettyPrint; window['PR'] = { 'createSimpleLexer': createSimpleLexer, 'registerLangHandler': registerLangHandler, 'sourceDecorator': sourceDecorator, 'PR_ATTRIB_NAME': PR_ATTRIB_NAME, 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE, 'PR_COMMENT': PR_COMMENT, 'PR_DECLARATION': PR_DECLARATION, 'PR_KEYWORD': PR_KEYWORD, 'PR_LITERAL': PR_LITERAL, 'PR_NOCODE': PR_NOCODE, 'PR_PLAIN': PR_PLAIN, 'PR_PUNCTUATION': PR_PUNCTUATION, 'PR_SOURCE': PR_SOURCE, 'PR_STRING': PR_STRING, 'PR_TAG': PR_TAG, 'PR_TYPE': PR_TYPE }; })();
++var PR_SHOULD_USE_CONTINUATION = true; var PR_TAB_WIDTH = 8; var PR_normalizedHtml; var PR; var prettyPrintOne; var prettyPrint; function _pr_isIE6() { var isIE6 = navigator && navigator.userAgent && /\bMSIE 6\./.test(navigator.userAgent); _pr_isIE6 = function() { return isIE6; }; return isIE6; } (function() { function wordSet(words) { words = words.split(/ /g); var set = {}; for (var i = words.length; --i >= 0; ) { var w = words[i]; if (w) { set[w] = null; } } return set; } var FLOW_CONTROL_KEYWORDS = "break continue do else for if return while "; var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " + "double enum extern float goto int long register short signed sizeof " + "static struct switch typedef union unsigned void volatile "; var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " + "new operator private protected public this throw true try "; var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " + "concept concept_map const_cast constexpr decltype " + "dynamic_cast explicit export friend inline late_check " + "mutable namespace nullptr reinterpret_cast static_assert static_cast " + "template typeid typename typeof using virtual wchar_t where "; var JAVA_KEYWORDS = COMMON_KEYWORDS + "boolean byte extends final finally implements import instanceof null " + "native package strictfp super synchronized throws transient "; var CSHARP_KEYWORDS = JAVA_KEYWORDS + "as base by checked decimal delegate descending event " + "fixed foreach from group implicit in interface internal into is lock " + "object out override orderby params readonly ref sbyte sealed " + "stackalloc string select uint ulong unchecked unsafe ushort var "; var JSCRIPT_KEYWORDS = COMMON_KEYWORDS + "debugger eval export function get null set undefined var with " + "Infinity NaN "; var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " + "goto if import last local my next no our print package redo require " + "sub undef unless until use wantarray while BEGIN END "; var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " + "elif except exec finally from global import in is lambda " + "nonlocal not or pass print raise try with yield " + "False True None "; var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" + " defined elsif end ensure false in module next nil not or redo rescue " + "retry self super then true undef unless until when yield BEGIN END "; var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " + "function in local set then until "; var ALL_KEYWORDS = (CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS + PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS); var PR_STRING = 'str'; var PR_KEYWORD = 'kwd'; var PR_COMMENT = 'com'; var PR_TYPE = 'typ'; var PR_LITERAL = 'lit'; var PR_PUNCTUATION = 'pun'; var PR_PLAIN = 'pln'; var PR_TAG = 'tag'; var PR_DECLARATION = 'dec'; var PR_SOURCE = 'src'; var PR_ATTRIB_NAME = 'atn'; var PR_ATTRIB_VALUE = 'atv'; var PR_NOCODE = 'nocode'; function isWordChar(ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); } function spliceArrayInto(inserted, container, containerPosition, countReplaced) { inserted.unshift(containerPosition, countReplaced || 0); try { container.splice.apply(container, inserted); } finally { inserted.splice(0, 2); } } var REGEXP_PRECEDER_PATTERN = function() { var preceders = ["!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=", "&=", "(", "*", "*=", "+=", ",", "-=", "->", "/", "/=", ":", "::", ";", "<", "<<", "<<=", "<=", "=", "==", "===", ">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", "^", "^=", "^^", "^^=", "{", "|", "|=", "||", "||=", "~", "break", "case", "continue", "delete", "do", "else", "finally", "instanceof", "return", "throw", "try", "typeof"]; var pattern = '(?:' + '(?:(?:^|[^0-9.])\\.{1,3})|' + '(?:(?:^|[^\\+])\\+)|' + '(?:(?:^|[^\\-])-)'; for (var i = 0; i < preceders.length; ++i) { var preceder = preceders[i]; if (isWordChar(preceder.charAt(0))) { pattern += '|\\b' + preceder; } else { pattern += '|' + preceder.replace(/([^=<>:&])/g, '\\$1'); } } pattern += '|^)\\s*$'; return new RegExp(pattern); } (); var pr_amp = /&/g; var pr_lt = /</g; var pr_gt = />/g; var pr_quot = /\"/g; function attribToHtml(str) { return str.replace(pr_amp, '&amp;').replace(pr_lt, '&lt;').replace(pr_gt, '&gt;').replace(pr_quot, '&quot;'); } function textToHtml(str) { return str.replace(pr_amp, '&amp;').replace(pr_lt, '&lt;').replace(pr_gt, '&gt;'); } var pr_ltEnt = /&lt;/g; var pr_gtEnt = /&gt;/g; var pr_aposEnt = /&apos;/g; var pr_quotEnt = /&quot;/g; var pr_ampEnt = /&amp;/g; var pr_nbspEnt = /&nbsp;/g; function htmlToText(html) { var pos = html.indexOf('&'); if (pos < 0) { return html; } for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0; ) { var end = html.indexOf(';', pos); if (end >= 0) { var num = html.substring(pos + 3, end); var radix = 10; if (num && num.charAt(0) === 'x') { num = num.substring(1); radix = 16; } var codePoint = parseInt(num, radix); if (!isNaN(codePoint)) { html = (html.substring(0, pos) + String.fromCharCode(codePoint) + html.substring(end + 1)); } } } return html.replace(pr_ltEnt, '<').replace(pr_gtEnt, '>').replace(pr_aposEnt, "'").replace(pr_quotEnt, '"').replace(pr_ampEnt, '&').replace(pr_nbspEnt, ' '); } function isRawContent(node) { return 'XMP' === node.tagName; } function normalizedHtml(node, out) { switch (node.nodeType) { case 1: var name = node.tagName.toLowerCase(); out.push('<', name); for (var i = 0; i < node.attributes.length; ++i) { var attr = node.attributes[i]; if (!attr.specified) { continue; } out.push(' '); normalizedHtml(attr, out); } out.push('>'); for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } if (node.firstChild || !/^(?:br|link|img)$/.test(name)) { out.push('<\/', name, '>'); } break; case 2: out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"'); break; case 3: case 4: out.push(textToHtml(node.nodeValue)); break; } } var PR_innerHtmlWorks = null; function getInnerHtml(node) { if (null === PR_innerHtmlWorks) { var testNode = document.createElement('PRE'); testNode.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />')); PR_innerHtmlWorks = !/</.test(testNode.innerHTML); } if (PR_innerHtmlWorks) { var content = node.innerHTML; if (isRawContent(node)) { content = textToHtml(content); } return content; } var out = []; for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } return out.join(''); } function makeTabExpander(tabWidth) { var SPACES = ' '; var charInLine = 0; return function(plainText) { var out = null; var pos = 0; for (var i = 0, n = plainText.length; i < n; ++i) { var ch = plainText.charAt(i); switch (ch) { case '\t': if (!out) { out = []; } out.push(plainText.substring(pos, i)); var nSpaces = tabWidth - (charInLine % tabWidth); charInLine += nSpaces; for (; nSpaces >= 0; nSpaces -= SPACES.length) { out.push(SPACES.substring(0, nSpaces)); } pos = i + 1; break; case '\n': charInLine = 0; break; default: ++charInLine; } } if (!out) { return plainText; } out.push(plainText.substring(pos)); return out.join(''); }; } var pr_chunkPattern = /(?:[^<]+|<!--[\s\S]*?-->|<!\[CDATA\[([\s\S]*?)\]\]>|<\/?[a-zA-Z][^>]*>|<)/g; var pr_commentPrefix = /^<!--/; var pr_cdataPrefix = /^<\[CDATA\[/; var pr_brPrefix = /^<br\b/i; var pr_tagNameRe = /^<(\/?)([a-zA-Z]+)/; function extractTags(s) { var matches = s.match(pr_chunkPattern); var sourceBuf = []; var sourceBufLen = 0; var extractedTags = []; if (matches) { for (var i = 0, n = matches.length; i < n; ++i) { var match = matches[i]; if (match.length > 1 && match.charAt(0) === '<') { if (pr_commentPrefix.test(match)) { continue; } if (pr_cdataPrefix.test(match)) { sourceBuf.push(match.substring(9, match.length - 3)); sourceBufLen += match.length - 12; } else if (pr_brPrefix.test(match)) { sourceBuf.push('\n'); ++sourceBufLen; } else { if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) { var name = match.match(pr_tagNameRe)[2]; var depth = 1; end_tag_loop: for (var j = i + 1; j < n; ++j) { var name2 = matches[j].match(pr_tagNameRe); if (name2 && name2[2] === name) { if (name2[1] === '/') { if (--depth === 0) { break end_tag_loop; } } else { ++depth; } } } if (j < n) { extractedTags.push(sourceBufLen, matches.slice(i, j + 1).join('')); i = j; } else { extractedTags.push(sourceBufLen, match); } } else { extractedTags.push(sourceBufLen, match); } } } else { var literalText = htmlToText(match); sourceBuf.push(literalText); sourceBufLen += literalText.length; } } } return { source: sourceBuf.join(''), tags: extractedTags }; } function isNoCodeTag(tag) { return !!tag.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g, ' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/); } function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) { var shortcuts = {}; (function() { var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns); for (var i = allPatterns.length; --i >= 0; ) { var patternParts = allPatterns[i]; var shortcutChars = patternParts[3]; if (shortcutChars) { for (var c = shortcutChars.length; --c >= 0; ) { shortcuts[shortcutChars.charAt(c)] = patternParts; } } } })(); var nPatterns = fallthroughStylePatterns.length; var notWs = /\S/; return function(sourceCode, opt_basePos) { opt_basePos = opt_basePos || 0; var decorations = [opt_basePos, PR_PLAIN]; var lastToken = ''; var pos = 0; var tail = sourceCode; while (tail.length) { var style; var token = null; var match; var patternParts = shortcuts[tail.charAt(0)]; if (patternParts) { match = tail.match(patternParts[1]); token = match[0]; style = patternParts[0]; } else { for (var i = 0; i < nPatterns; ++i) { patternParts = fallthroughStylePatterns[i]; var contextPattern = patternParts[2]; if (contextPattern && !contextPattern.test(lastToken)) { continue; } match = tail.match(patternParts[1]); if (match) { token = match[0]; style = patternParts[0]; break; } } if (!token) { style = PR_PLAIN; token = tail.substring(0, 1); } } decorations.push(opt_basePos + pos, style); pos += token.length; tail = tail.substring(token.length); if (style !== PR_COMMENT && notWs.test(token)) { lastToken = token; } } return decorations; }; } var PR_MARKUP_LEXER = createSimpleLexer([], [[PR_PLAIN, /^[^<]+/, null], [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/, null], [PR_COMMENT, /^<!--[\s\S]*?(?:-->|$)/, null], [PR_SOURCE, /^<\?[\s\S]*?(?:\?>|$)/, null], [PR_SOURCE, /^<%[\s\S]*?(?:%>|$)/, null], [PR_SOURCE, /^<(script|style|xmp)\b[^>]*>[\s\S]*?<\/\1\b[^>]*>/i, null], [PR_TAG, /^<\/?\w[^<>]*>/, null]]); var PR_SOURCE_CHUNK_PARTS = /^(<[^>]*>)([\s\S]*)(<\/[^>]*>)$/; function tokenizeMarkup(source) { var decorations = PR_MARKUP_LEXER(source); for (var i = 0; i < decorations.length; i += 2) { if (decorations[i + 1] === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var sourceChunk = source.substring(start, end); var match = sourceChunk.match(PR_SOURCE_CHUNK_PARTS); if (match) { decorations.splice(i, 2, start, PR_TAG, start + match[1].length, PR_SOURCE, start + match[1].length + (match[2] || '').length, PR_TAG); } } } return decorations; } var PR_TAG_LEXER = createSimpleLexer([[PR_ATTRIB_VALUE, /^\'[^\']*(?:\'|$)/, null, "'"], [PR_ATTRIB_VALUE, /^\"[^\"]*(?:\"|$)/, null, '"'], [PR_PUNCTUATION, /^[<>\/=]+/, null, '<>/=']], [[PR_TAG, /^[\w:\-]+/, /^</], [PR_ATTRIB_VALUE, /^[\w\-]+/, /^=/], [PR_ATTRIB_NAME, /^[\w:\-]+/, null], [PR_PLAIN, /^\s+/, null, ' \t\r\n']]); function splitTagAttributes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_TAG) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var chunk = source.substring(start, end); var subDecorations = PR_TAG_LEXER(chunk, start); spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function sourceDecorator(options) { var shortcutStylePatterns = [], fallthroughStylePatterns = []; if (options.tripleQuotedStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, null, '\'"']); } else if (options.multiLineStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, null, '\'"`']); } else { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, null, '"\'']); } fallthroughStylePatterns.push([PR_PLAIN, /^(?:[^\'\"\`\/\#]+)/, null, ' \r\n']); if (options.hashComments) { shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']); } if (options.cStyleComments) { fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]); fallthroughStylePatterns.push([PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); } if (options.regexLiterals) { var REGEX_LITERAL = ('^/(?=[^/*])' + '(?:[^/\\x5B\\x5C]' + '|\\x5C[\\s\\S]' + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+' + '(?:/|$)'); fallthroughStylePatterns.push([PR_STRING, new RegExp(REGEX_LITERAL), REGEXP_PRECEDER_PATTERN]); } var keywords = wordSet(options.keywords); options = null; var splitStringAndCommentTokens = createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns); var styleLiteralIdentifierPuncRecognizer = createSimpleLexer([], [[PR_PLAIN, /^\s+/, null, ' \r\n'], [PR_PLAIN, /^[a-z_$@][a-z_$@0-9]*/i, null], [PR_LITERAL, /^0x[a-f0-9]+[a-z]/i, null], [PR_LITERAL, /^(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?[a-z]*/i, null, '123456789'], [PR_PUNCTUATION, /^[^\s\w\.$@]+/, null]]); function splitNonStringNonCommentTokens(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_PLAIN) { var start, end, chunk, subDecs; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; chunk = source.substring(start, end); subDecs = styleLiteralIdentifierPuncRecognizer(chunk, start); for (var j = 0, m = subDecs.length; j < m; j += 2) { var subStyle = subDecs[j + 1]; if (subStyle === PR_PLAIN) { var subStart = subDecs[j]; var subEnd = j + 2 < m ? subDecs[j + 2] : chunk.length; var token = source.substring(subStart, subEnd); if (token === '.') { subDecs[j + 1] = PR_PUNCTUATION; } else if (token in keywords) { subDecs[j + 1] = PR_KEYWORD; } else if (/^@?[A-Z][A-Z$]*[a-z][A-Za-z$]*$/.test(token)) { subDecs[j + 1] = token.charAt(0) === '@' ? PR_LITERAL : PR_TYPE; } } } spliceArrayInto(subDecs, decorations, i, 2); i += subDecs.length - 2; } } return decorations; } return function(sourceCode) { var decorations = splitStringAndCommentTokens(sourceCode); decorations = splitNonStringNonCommentTokens(sourceCode, decorations); return decorations; }; } var decorateSource = sourceDecorator({ keywords: ALL_KEYWORDS, hashComments: true, cStyleComments: true, multiLineStrings: true, regexLiterals: true }); function splitSourceNodes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var subDecorations = decorateSource(source.substring(start, end)); for (var j = 0, m = subDecorations.length; j < m; j += 2) { subDecorations[j] += start; } spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function splitSourceAttributes(source, decorations) { var nextValueIsSource = false; for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; var start, end; if (style === PR_ATTRIB_NAME) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; nextValueIsSource = /^on|^style$/i.test(source.substring(start, end)); } else if (style === PR_ATTRIB_VALUE) { if (nextValueIsSource) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var attribValue = source.substring(start, end); var attribLen = attribValue.length; var quoted = (attribLen >= 2 && /^[\"\']/.test(attribValue) && attribValue.charAt(0) === attribValue.charAt(attribLen - 1)); var attribSource; var attribSourceStart; var attribSourceEnd; if (quoted) { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue; } else { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue.substring(1, attribValue.length - 1); } var attribSourceDecorations = decorateSource(attribSource); for (var j = 0, m = attribSourceDecorations.length; j < m; j += 2) { attribSourceDecorations[j] += attribSourceStart; } if (quoted) { attribSourceDecorations.push(attribSourceEnd, PR_ATTRIB_VALUE); spliceArrayInto(attribSourceDecorations, decorations, i + 2, 0); } else { spliceArrayInto(attribSourceDecorations, decorations, i, 2); } } nextValueIsSource = false; } } return decorations; } function decorateMarkup(sourceCode) { var decorations = tokenizeMarkup(sourceCode); decorations = splitTagAttributes(sourceCode, decorations); decorations = splitSourceNodes(sourceCode, decorations); decorations = splitSourceAttributes(sourceCode, decorations); return decorations; } function recombineTagsAndDecorations(sourceText, extractedTags, decorations) { var html = []; var outputIdx = 0; var openDecoration = null; var currentDecoration = null; var tagPos = 0; var decPos = 0; var tabExpander = makeTabExpander(PR_TAB_WIDTH); var adjacentSpaceRe = /([\r\n ]) /g; var startOrSpaceRe = /(^| ) /gm; var newlineRe = /\r\n?|\n/g; var trailingSpaceRe = /[ \r\n]$/; var lastWasSpace = true; function emitTextUpTo(sourceIdx) { if (sourceIdx > outputIdx) { if (openDecoration && openDecoration !== currentDecoration) { html.push('</span>'); openDecoration = null; } if (!openDecoration && currentDecoration) { openDecoration = currentDecoration; html.push('<span class="', openDecoration, '">'); } var htmlChunk = textToHtml(tabExpander(sourceText.substring(outputIdx, sourceIdx))).replace(lastWasSpace ? startOrSpaceRe : adjacentSpaceRe, '$1&nbsp;'); lastWasSpace = trailingSpaceRe.test(htmlChunk); html.push(htmlChunk.replace(newlineRe, '<br />')); outputIdx = sourceIdx; } } while (true) { var outputTag; if (tagPos < extractedTags.length) { if (decPos < decorations.length) { outputTag = extractedTags[tagPos] <= decorations[decPos]; } else { outputTag = true; } } else { outputTag = false; } if (outputTag) { emitTextUpTo(extractedTags[tagPos]); if (openDecoration) { html.push('</span>'); openDecoration = null; } html.push(extractedTags[tagPos + 1]); tagPos += 2; } else if (decPos < decorations.length) { emitTextUpTo(decorations[decPos]); currentDecoration = decorations[decPos + 1]; decPos += 2; } else { break; } } emitTextUpTo(sourceText.length); if (openDecoration) { html.push('</span>'); } return html.join(''); } var langHandlerRegistry = {}; function registerLangHandler(handler, fileExtensions) { for (var i = fileExtensions.length; --i >= 0; ) { var ext = fileExtensions[i]; if (!langHandlerRegistry.hasOwnProperty(ext)) { langHandlerRegistry[ext] = handler; } else if ('console' in window) { console.log('cannot override language handler %s', ext); } } } registerLangHandler(decorateSource, ['default-code']); registerLangHandler(decorateMarkup, ['default-markup', 'html', 'htm', 'xhtml', 'xml', 'xsl']); registerLangHandler(sourceDecorator({ keywords: CPP_KEYWORDS, hashComments: true, cStyleComments: true }), ['c', 'cc', 'cpp', 'cs', 'cxx', 'cyc']); registerLangHandler(sourceDecorator({ keywords: JAVA_KEYWORDS, cStyleComments: true }), ['java']); registerLangHandler(sourceDecorator({ keywords: SH_KEYWORDS, hashComments: true, multiLineStrings: true }), ['bsh', 'csh', 'sh']); registerLangHandler(sourceDecorator({ keywords: PYTHON_KEYWORDS, hashComments: true, multiLineStrings: true, tripleQuotedStrings: true }), ['cv', 'py']); registerLangHandler(sourceDecorator({ keywords: PERL_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['perl', 'pl', 'pm']); registerLangHandler(sourceDecorator({ keywords: RUBY_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['rb']); registerLangHandler(sourceDecorator({ keywords: JSCRIPT_KEYWORDS, cStyleComments: true, regexLiterals: true }), ['js']); function prettyPrintOne(sourceCodeHtml, opt_langExtension) { try { var sourceAndExtractedTags = extractTags(sourceCodeHtml); var source = sourceAndExtractedTags.source; var extractedTags = sourceAndExtractedTags.tags; if (!langHandlerRegistry.hasOwnProperty(opt_langExtension)) { opt_langExtension = /^\s*</.test(source) ? 'default-markup' : 'default-code'; } var decorations = langHandlerRegistry[opt_langExtension].call({}, source); return recombineTagsAndDecorations(source, extractedTags, decorations); } catch (e) { if ('console' in window) { console.log(e); console.trace(); } return sourceCodeHtml; } } function prettyPrint(opt_whenDone) { var isIE6 = _pr_isIE6(); var codeSegments = [document.getElementsByTagName('pre'), document.getElementsByTagName('code'), document.getElementsByTagName('xmp')]; var elements = []; for (var i = 0; i < codeSegments.length; ++i) { for (var j = 0; j < codeSegments[i].length; ++j) { elements.push(codeSegments[i][j]); } } codeSegments = null; var k = 0; function doWork() { var endTime = (PR_SHOULD_USE_CONTINUATION ? new Date().getTime() + 250 : Infinity); for (; k < elements.length && new Date().getTime() < endTime; k++) { var cs = elements[k]; if (cs.className && cs.className.indexOf('prettyprint') >= 0) { var langExtension = cs.className.match(/\blang-(\w+)\b/); if (langExtension) { langExtension = langExtension[1]; } var nested = false; for (var p = cs.parentNode; p; p = p.parentNode) { if ((p.tagName === 'pre' || p.tagName === 'code' || p.tagName === 'xmp') && p.className && p.className.indexOf('prettyprint') >= 0) { nested = true; break; } } if (!nested) { var content = getInnerHtml(cs); content = content.replace(/(?:\r\n?|\n)$/, ''); var newContent = prettyPrintOne(content, langExtension); if (!isRawContent(cs)) { cs.innerHTML = newContent; } else { var pre = document.createElement('PRE'); for (var i = 0; i < cs.attributes.length; ++i) { var a = cs.attributes[i]; if (a.specified) { var aname = a.name.toLowerCase(); if (aname === 'class') { pre.className = a.value; } else { pre.setAttribute(a.name, a.value); } } } pre.innerHTML = newContent; cs.parentNode.replaceChild(pre, cs); cs = pre; } if (isIE6 && cs.tagName === 'PRE') { var lineBreaks = cs.getElementsByTagName('br'); for (var j = lineBreaks.length; --j >= 0; ) { var lineBreak = lineBreaks[j]; lineBreak.parentNode.replaceChild(document.createTextNode('\r\n'), lineBreak); } } } } } if (k < elements.length) { setTimeout(doWork, 250); } else if (opt_whenDone) { opt_whenDone(); } } doWork(); } window['PR_normalizedHtml'] = normalizedHtml; window['prettyPrintOne'] = prettyPrintOne; window['prettyPrint'] = prettyPrint; window['PR'] = { 'createSimpleLexer': createSimpleLexer, 'registerLangHandler': registerLangHandler, 'sourceDecorator': sourceDecorator, 'PR_ATTRIB_NAME': PR_ATTRIB_NAME, 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE, 'PR_COMMENT': PR_COMMENT, 'PR_DECLARATION': PR_DECLARATION, 'PR_KEYWORD': PR_KEYWORD, 'PR_LITERAL': PR_LITERAL, 'PR_NOCODE': PR_NOCODE, 'PR_PLAIN': PR_PLAIN, 'PR_PUNCTUATION': PR_PUNCTUATION, 'PR_SOURCE': PR_SOURCE, 'PR_STRING': PR_STRING, 'PR_TAG': PR_TAG, 'PR_TYPE': PR_TYPE }; })();
+\ No newline at end of file
+diff -ruN CNPROG/templates/content/js/com.cnprog.utils.js mikes/templates/content/js/com.cnprog.utils.js
+--- CNPROG/templates/content/js/com.cnprog.utils.js 2009-06-22 21:42:51.000000000 -0400
++++ mikes/templates/content/js/com.cnprog.utils.js 2009-07-25 19:09:58.138152577 -0400
+@@ -119,4 +113,4 @@
+ }();
+ //Search Engine Keyword Highlight with Javascript
+ //http://scott.yang.id.au/code/se-hilite/
+-Hilite={elementid:"content",exact:true,max_nodes:1000,onload:true,style_name:"hilite",style_name_suffix:true,debug_referrer:""};Hilite.search_engines=[["local","q"],["cnprog\\.","q"],["google\\.","q"],["search\\.yahoo\\.","p"],["search\\.msn\\.","q"],["search\\.live\\.","query"],["search\\.aol\\.","userQuery"],["ask\\.com","q"],["altavista\\.","q"],["feedster\\.","q"],["search\\.lycos\\.","q"],["alltheweb\\.","q"],["technorati\\.com/search/([^\\?/]+)",1],["dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)",1,true]];Hilite.decodeReferrer=function(d){var g=null;var e=new RegExp("");for(var c=0;c<Hilite.search_engines.length;c++){var f=Hilite.search_engines[c];e.compile("^http://(www\\.)?"+f[0],"i");var b=d.match(e);if(b){var a;if(isNaN(f[1])){a=Hilite.decodeReferrerQS(d,f[1])}else{a=b[f[1]+1]}if(a){a=decodeURIComponent(a);if(f.length>2&&f[2]){a=decodeURIComponent(a)}a=a.replace(/\'|"/g,"");a=a.split(/[\s,\+\.]+/);return a}break}}return null};Hilite.decodeReferrerQS=function(f,d){var b=f.indexOf("?");var c;if(b>=0){var a=new String(f.substring(b+1));b=0;c=0;while((b>=0)&&((c=a.indexOf("=",b))>=0)){var e,g;e=a.substring(b,c);b=a.indexOf("&",c)+1;if(e==d){if(b<=0){return a.substring(c+1)}else{return a.substring(c+1,b-1)}}else{if(b<=0){return null}}}}return null};Hilite.hiliteElement=function(f,e){if(!e||f.childNodes.length==0){return}var c=new Array();for(var b=0;b<e.length;b++){e[b]=e[b].toLowerCase();if(Hilite.exact){c.push("\\b"+e[b]+"\\b")}else{c.push(e[b])}}c=new RegExp(c.join("|"),"i");var a={};for(var b=0;b<e.length;b++){if(Hilite.style_name_suffix){a[e[b]]=Hilite.style_name+(b+1)}else{a[e[b]]=Hilite.style_name}}var d=function(m){var j=c.exec(m.data);if(j){var n=j[0];var i="";var h=m.splitText(j.index);var g=h.splitText(n.length);var l=m.ownerDocument.createElement("SPAN");m.parentNode.replaceChild(l,h);l.className=a[n.toLowerCase()];l.appendChild(h);return l}else{return m}};Hilite.walkElements(f.childNodes[0],1,d)};Hilite.hilite=function(){var a=Hilite.debug_referrer?Hilite.debug_referrer:document.referrer;var b=null;a=Hilite.decodeReferrer(a);if(a&&((Hilite.elementid&&(b=document.getElementById(Hilite.elementid)))||(b=document.body))){Hilite.hiliteElement(b,a)}};Hilite.walkElements=function(d,f,e){var a=/^(script|style|textarea)/i;var c=0;while(d&&f>0){c++;if(c>=Hilite.max_nodes){var b=function(){Hilite.walkElements(d,f,e)};setTimeout(b,50);return}if(d.nodeType==1){if(!a.test(d.tagName)&&d.childNodes.length>0){d=d.childNodes[0];f++;continue}}else{if(d.nodeType==3){d=e(d)}}if(d.nextSibling){d=d.nextSibling}else{while(f>0){d=d.parentNode;f--;if(d.nextSibling){d=d.nextSibling;break}}}}};if(Hilite.onload){if(window.attachEvent){window.attachEvent("onload",Hilite.hilite)}else{if(window.addEventListener){window.addEventListener("load",Hilite.hilite,false)}else{var __onload=window.onload;window.onload=function(){Hilite.hilite();__onload()}}}};
++Hilite={elementid:"content",exact:true,max_nodes:1000,onload:true,style_name:"hilite",style_name_suffix:true,debug_referrer:""};Hilite.search_engines=[["local","q"],["cnprog\\.","q"],["google\\.","q"],["search\\.yahoo\\.","p"],["search\\.msn\\.","q"],["search\\.live\\.","query"],["search\\.aol\\.","userQuery"],["ask\\.com","q"],["altavista\\.","q"],["feedster\\.","q"],["search\\.lycos\\.","q"],["alltheweb\\.","q"],["technorati\\.com/search/([^\\?/]+)",1],["dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)",1,true]];Hilite.decodeReferrer=function(d){var g=null;var e=new RegExp("");for(var c=0;c<Hilite.search_engines.length;c++){var f=Hilite.search_engines[c];e.compile("^http://(www\\.)?"+f[0],"i");var b=d.match(e);if(b){var a;if(isNaN(f[1])){a=Hilite.decodeReferrerQS(d,f[1])}else{a=b[f[1]+1]}if(a){a=decodeURIComponent(a);if(f.length>2&&f[2]){a=decodeURIComponent(a)}a=a.replace(/\'|"/g,"");a=a.split(/[\s,\+\.]+/);return a}break}}return null};Hilite.decodeReferrerQS=function(f,d){var b=f.indexOf("?");var c;if(b>=0){var a=new String(f.substring(b+1));b=0;c=0;while((b>=0)&&((c=a.indexOf("=",b))>=0)){var e,g;e=a.substring(b,c);b=a.indexOf("&",c)+1;if(e==d){if(b<=0){return a.substring(c+1)}else{return a.substring(c+1,b-1)}}else{if(b<=0){return null}}}}return null};Hilite.hiliteElement=function(f,e){if(!e||f.childNodes.length==0){return}var c=new Array();for(var b=0;b<e.length;b++){e[b]=e[b].toLowerCase();if(Hilite.exact){c.push("\\b"+e[b]+"\\b")}else{c.push(e[b])}}c=new RegExp(c.join("|"),"i");var a={};for(var b=0;b<e.length;b++){if(Hilite.style_name_suffix){a[e[b]]=Hilite.style_name+(b+1)}else{a[e[b]]=Hilite.style_name}}var d=function(m){var j=c.exec(m.data);if(j){var n=j[0];var i="";var h=m.splitText(j.index);var g=h.splitText(n.length);var l=m.ownerDocument.createElement("SPAN");m.parentNode.replaceChild(l,h);l.className=a[n.toLowerCase()];l.appendChild(h);return l}else{return m}};Hilite.walkElements(f.childNodes[0],1,d)};Hilite.hilite=function(){var a=Hilite.debug_referrer?Hilite.debug_referrer:document.referrer;var b=null;a=Hilite.decodeReferrer(a);if(a&&((Hilite.elementid&&(b=document.getElementById(Hilite.elementid)))||(b=document.body))){Hilite.hiliteElement(b,a)}};Hilite.walkElements=function(d,f,e){var a=/^(script|style|textarea)/i;var c=0;while(d&&f>0){c++;if(c>=Hilite.max_nodes){var b=function(){Hilite.walkElements(d,f,e)};setTimeout(b,50);return}if(d.nodeType==1){if(!a.test(d.tagName)&&d.childNodes.length>0){d=d.childNodes[0];f++;continue}}else{if(d.nodeType==3){d=e(d)}}if(d.nextSibling){d=d.nextSibling}else{while(f>0){d=d.parentNode;f--;if(d.nextSibling){d=d.nextSibling;break}}}}};if(Hilite.onload){if(window.attachEvent){window.attachEvent("onload",Hilite.hilite)}else{if(window.addEventListener){window.addEventListener("load",Hilite.hilite,false)}else{var __onload=window.onload;window.onload=function(){Hilite.hilite();__onload()}}}};
+\ No newline at end of file
+diff -ruN CNPROG/templates/content/style/openid.css mikes/templates/content/style/openid.css
+--- CNPROG/templates/content/style/openid.css 2009-06-22 21:42:51.000000000 -0400
++++ mikes/templates/content/style/openid.css 2009-07-25 19:09:58.168153308 -0400
+@@ -42,4 +42,4 @@
+ }
+ .openid_selected {
+ border: 4px solid #DDD;
+- }
++ }
+\ No newline at end of file
+diff -ruN CNPROG/templates/okfiles mikes/templates/okfiles
+--- CNPROG/templates/okfiles 2009-06-22 21:42:52.000000000 -0400
++++ mikes/templates/okfiles 1969-12-31 19:00:00.000000000 -0500
+@@ -1,30 +0,0 @@
+-404.html
+-500.html
+-about.html
+-ask.html
+-badges.html
+-base_content.html
+-base.html
+-book.html
+-close.html
+-faq.html
+-footer.html
+-header.html
+-index.html
+-logout.html
+-pagesize.html
+-paginator.html
+-privacy.html
+-question_edit_tips.html
+-question.html
+-questions.html
+-revisions_answer.html
+-tags.html
+-unanswered.html
+-user_edit.html
+-user_info.html
+-users.html
+-users_questions.html
+-user_stats.html
+-user_tabs.html
+-user_votes.html
+diff -ruN CNPROG/templates/pagesize.html mikes/templates/pagesize.html
+--- CNPROG/templates/pagesize.html 2009-06-22 21:42:52.000000000 -0400
++++ mikes/templates/pagesize.html 2009-07-25 19:09:58.168153308 -0400
+@@ -1,9 +1,8 @@
+-<!-- template pagesize.html -->
+ {% spaceless %}
+ {% load i18n %}
+ {% if is_paginated %}
+ <div class="paginator">
+- <span class="text">{% trans "posts per page" %}</span>
++ <span class="text">{% trans "Size per page:" %}</span>
+ {% ifequal pagesize 10 %}
+ <span class="curr">10</span>
+ {% else %}
+@@ -24,4 +23,3 @@
+ </div>
+ {% endif %}
+ {% endspaceless %}
+-<!-- end template pagesize.html -->
+diff -ruN CNPROG/templates/question_retag.html mikes/templates/question_retag.html
+--- CNPROG/templates/question_retag.html 1969-12-31 19:00:00.000000000 -0500
++++ mikes/templates/question_retag.html 2009-07-25 19:09:58.178152900 -0400
+@@ -0,0 +1,109 @@
++{% extends "base.html" %}
++{% block title %}{% spaceless %}修改问题标签{% endspaceless %}{% endblock %}
++{% block forejs %}
++ <script type='text/javascript' src='/content/js/com.cnprog.editor.js'></script>
++ <script type='text/javascript' src='/content/js/com.cnprog.post.js'></script>
++ <script type='text/javascript' src='/content/js/jquery.validate.pack.js'></script>
++ <script type="text/javascript">
++
++ $().ready(function(){
++ $("#nav_questions").attr('className',"on");
++ //Tags autocomplete action
++ var tags = {{ tags|safe }};
++ $("#id_tags").autocomplete(tags, {
++ minChars: 1,
++ matchContains: true,
++ max: 20,
++ multiple: true,
++ multipleSeparator: " ",
++ formatItem: function(row, i, max) {
++ return row.n + " ("+ row.c +")";
++ },
++ formatResult: function(row, i, max){
++ return row.n;
++ }
++
++ });
++
++ $("#fmretag").validate({
++ rules: {
++ tags: {
++ required: true,
++ maxength: 105
++ }
++ },
++ messages: {
++ tags: {
++ required: " 标签不能为空。",
++ maxlength: " 最多5个标签,每个标签长度小于20个字符。"
++ }
++ }
++
++ });
++ lanai.highlightSyntax();
++
++ });
++ </script>
++{% endblock %}
++
++{% block content %}
++<div id="main-bar" class="headNormal">
++ 修改标签 [<a href="{{ question.get_absolute_url }}">返回</a>]
++</div>
++<div id="main-body" class="ask-body">
++ <div id="askform">
++ <form id="fmretag" action="{% url edit_question question.id %}" method="post" >
++ <h3>
++ {{ question.get_question_title }}
++ </h3>
++ <div id="description" class="edit-content-html">
++ {{ question.html|safe }}
++ </div>
++
++
++ <div class="form-item">
++ <strong>{{ form.tags.label_tag }}:</strong> <span class="form-error"></span><br>
++ {{ form.tags }} {{ form.tags.errors }}
++ <div class="title-desc">
++ {{ form.tags.help_text }}
++ </div>
++ </div>
++ <br>
++
++ <div class="error" ></div>
++ <input type="submit" value="现在修改" class="submit" />
++ <input type="button" value="取消" class="submit" onclick="history.back(-1);" />
++ <br>
++ <br>
++ </form>
++ </div>
++</div>
++{% endblock %}
++
++{% block sidebar %}
++<div class="boxC">
++ <p class="subtitle">为什么我只能修改问题标签?</p>
++ <ul class="list-item">
++
++ <li>
++ CNProg用标签来分类系统的信息
++
++ </li>
++ <li>
++ 修改完整问题需要用户的积分达到一定条件(比如:积分 >= 3000分,自己发布的问题除外),而用户积分达到比较低的时候,就可以修改问题的标签(比如:积分 >= 500, 这里指所有问题的标签)。
++
++ </li>
++ <li>
++ 修改标签的用户将授予特殊的社区奖牌
++
++ </li>
++ </ul>
++ <a href="{% url faq %}" style="float:right;position:relative">faq »</a>
++ <br>
++</div>
++
++{% endblock %}
++
++{% block endjs %}
++{% endblock %}
++
+diff -ruN CNPROG/templates/template.list mikes/templates/template.list
+--- CNPROG/templates/template.list 2009-06-22 21:42:52.000000000 -0400
++++ mikes/templates/template.list 1969-12-31 19:00:00.000000000 -0500
+@@ -1,18 +0,0 @@
+-close.html
+-book.html
+-base_content.html
+-badges.html
+-badge.html
+-ask.html
+-answer_edit_tips.html
+-answer_edit.html
+-about.html
+-500.html
+-404.html
+-pagesize.html
+-logout.html
+-header.html
+-footer.html
+-faq.html
+-base.html
+-question.html
+diff -ruN CNPROG/templates/tough/faq.html mikes/templates/tough/faq.html
+--- CNPROG/templates/tough/faq.html 2009-06-22 21:42:52.000000000 -0400
++++ mikes/templates/tough/faq.html 1969-12-31 19:00:00.000000000 -0500
+@@ -1,110 +0,0 @@
+-{% extends "base_content.html" %}
+-{% load extra_tags %}
+-{% load humanize %}
+-{% block title %}{% spaceless %}FAQ{% endspaceless %}{% endblock %}
+-{% block forejs %}
+-{% endblock %}
+-{% block content %}
+-<div class="headNormal">
+- {% trans "Frequently Asked Questions " %}(FAQ)
+-</div>
+-<div id="main-body" style="width:100%">
+-
+- <h3 class="subtitle">{% trans "What kinds of questions can I ask here?" %}</h3>
+- <p>{% trans "Most importanly - questions should be <strong>relevant</strong> to this community." %}<br>
+- {% trans "Before asking the question - please make sure to use search to see whether your question has alredy been answered."%}<br>
+- </p><br>
+-
+- <h3 class="subtitle">{% trans "What questions should I avoid asking?" %}</h3>
+- <p>{% trans "Please avoid asking questions that are not relevant to this community, too subjective and argumentative." %}</p>
+- </p><br>
+-
+- <h3 class="subtitle">{% trans "What should I avoid in my answers?" %}</h3>
+- <p>{% trans "site title" %} {% trans "is a Q&A site, not a discussion group. Therefore - please avoid having discussions in your answers, comment facility allows some space for brief discussions." %}
+- </p><br>
+-
+- <h3 class="subtitle">{% trans "Who moderates this community?" %}</h3>
+- <p>{% trans "The short answer is: <strong>you</strong>." %}<br>
+- {% trans "This website is moderated by the users." %}
+- {% trans "The reputation system allows users earn the authorization to perform a variety of moderation tasks." %}
+- </p><br>
+-
+- <h3 class="subtitle">{% trans "How does reputation system work?" %}</h3>
+- <p>{% trans "Anyone can ask questions and give answers, points are not necessary for that." %}<br>
+- {% trans "As we've said before, users help running this site. Point system helps select users who can administer this community."%}
+- {% trans "Reputation points roughly measure how community trusts you. These points are given to you directly by other members of the community." %}
+- </p>
+- <p>
+- {% trans "For example, if you ask an interesting question or give a helpful answer, your input will be upvoted and you will gain more trust in the community." %}
+- {% trans "If on the other hand someone gives a misleading answer, the answer will be voted down and he/she loses some points." %}
+- {% trans "Each vote in favor will generate <strong>10</strong> points, each vote against will subtract <strong>2</strong> points." trans %}
+- {% trans "Through the votes of other people you can accumulate a maximum of <strong>200</strong> points." %}
+- {% "After accumulating certain number of points, you can do more:" %}
+- <table style="font-family:arial;" cellspacing="3" cellpadding="3">
+- <tr>
+- <th width="40px" style="text-align:right"></th>
+- <th width="300px"></th>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>15</strong></td>
+- <td>{% trans "upvote" %}</td>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>15</strong></td>
+- <td>{% trans "use tags" %}</td>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>50</strong></td>
+- <td>{% trans "add comments" %}</td>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>100</strong></td>
+- <td>{% trans "downvote" %}</td>
+- </tr><tr>
+- <td style="text-align:right;padding-right:5px"><strong>250</strong></td>
+- <td>打开关闭自己的问题</td>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>500</strong></td>
+- <td>{% trans "retag questions" %}</td>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>750</strong></td>
+- <td>{% trans "edit community wiki questions" %}</td>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>2000</strong></td>
+- <td>{% trans "edit any answer" %}</td>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>3000</strong></td>
+- <td>{% trans "open any closed question" %}</td>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>5000</strong></td>
+- <td>{% trans "delete any comment" %}</td>
+- </tr>
+- <tr>
+- <td style="text-align:right;padding-right:5px"><strong>10000</strong></td>
+- <td>{% trans "delete any questions and answers and perform other moderation tasks" %}</td>
+- </tr>
+-
+- </table>
+-
+- </p><br>
+-
+- <h3 class="subtitle">{% trans "To register, do I need to create new password?"</h3>
+- <p>{% trans "No, you don't have to. You can login through any service that supports OpenID, e.g. Google, Yahoo, AOL, etc." %}
+- <strong><a href="/account/signin">{% trans "Login now!" %}</a> »</strong>
+- </p><br>
+-
+- <h3 class="subtitle">{% trans "Why other people can edit my questions/answers?" %}</h3>
+- <p> {% trans "Goal of this site is..." %} {% trans "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." %}
+- {% trans "If this approach is not for you, we respect your choice." %}
+- </p><br>
+- <h3 class="subtitle">{% trans "Still have questions?" %}</h3>
+- <p>{% "Please ask your question, help make our community better!" %} <a href="/tags/faq" class="big">{% trans "site title" %} {% trans "questions" %}</a>{% trans "." %}
+- </p>
+- <br><br>
+-</div>
+-{% endblock %}
+diff -ruN CNPROG/templates/tough/question_retag.html mikes/templates/tough/question_retag.html
+--- CNPROG/templates/tough/question_retag.html 2009-06-22 21:42:52.000000000 -0400
++++ mikes/templates/tough/question_retag.html 1969-12-31 19:00:00.000000000 -0500
+@@ -1,107 +0,0 @@
+-{% extends "base.html" %}
+-{% block title %}{% spaceless %}{% trans "Revise tags" %}{% endspaceless %}{% endblock %}
+-{% block forejs %}
+- <script type='text/javascript' src='/content/js/com.cnprog.editor.js'></script>
+- <script type='text/javascript' src='/content/js/com.cnprog.post.js'></script>
+- <script type='text/javascript' src='/content/js/jquery.validate.pack.js'></script>
+- <script type="text/javascript">
+-
+- $().ready(function(){
+- $("#nav_questions").attr('className',"on");
+- //Tags autocomplete action
+- var tags = {{ tags|safe }};
+- $("#id_tags").autocomplete(tags, {
+- minChars: 1,
+- matchContains: true,
+- max: 20,
+- multiple: true,
+- multipleSeparator: " ",
+- formatItem: function(row, i, max) {
+- return row.n + " ("+ row.c +")";
+- },
+- formatResult: function(row, i, max){
+- return row.n;
+- }
+-
+- });
+-
+- $("#fmretag").validate({
+- rules: {
+- tags: {
+- required: true,
+- maxength: 105
+- }
+- },
+- messages: {
+- tags: {
+- required: ' ' + {% trans "tags are requried" %},
+- maxlength: ' ' + {% trans "up to 5 tags, less than 20 characters each" %},
+- }
+- }
+-
+- });
+- lanai.highlightSyntax();
+-
+- });
+- </script>
+-{% endblock %}
+-
+-{% block content %}
+-<div id="main-bar" class="headNormal">
+- {% trans "Change tags" %} [<a href="{{ question.get_absolute_url }}">{% trans "back" %}</a>]
+-</div>
+-<div id="main-body" class="ask-body">
+- <div id="askform">
+- <form id="fmretag" action="{% url edit_question question.id %}" method="post" >
+- <h3>
+- {{ question.get_question_title }}
+- </h3>
+- <div id="description" class="edit-content-html">
+- {{ question.html|safe }}
+- </div>
+-
+-
+- <div class="form-item">
+- <strong>{{ form.tags.label_tag }}:</strong> <span class="form-error"></span><br>
+- {{ form.tags }} {{ form.tags.errors }}
+- <div class="title-desc">
+- {{ form.tags.help_text }}
+- </div>
+- </div>
+- <br>
+-
+- <div class="error" ></div>
+- <input type="submit" value="{% trans "Change now" %}" class="submit" />
+- <input type="button" value="{% trans "Cancel" %}" class="submit" onclick="history.back(-1);" />
+- <br>
+- <br>
+- </form>
+- </div>
+-</div>
+-{% endblock %}
+-
+-{% block sidebar %}
+-<div class="boxC">
+- <p class="subtitle">{% trans "Why use and modify tags?" %}</p>
+- <ul class="list-item">
+-
+- <li>
+- {% trans "site title" %} {% trans "uses tags for the classification of questions %}
+- </li>
+- <li>
+- 修改完整问题需要用户的积分达到一定条件(比如:积分 >= 3000分,自己发布的问题除外),而用户积分达到比较低的时候,就可以修改问题的标签(比如:积分 >= 500, 这里指所有问题的标签)。
+-
+- </li>
+- <li>
+- {% trans "tag editors receive special awards from the community" %}
+- </li>
+- </ul>
+- <a href="{% url faq %}" style="float:right;position:relative">faq »</a>
+- <br>
+-</div>
+-
+-{% endblock %}
+-
+-{% block endjs %}
+-{% endblock %}
+-
+diff -ruN CNPROG/templates/tough/unanswered.html mikes/templates/tough/unanswered.html
+--- CNPROG/templates/tough/unanswered.html 2009-06-22 21:42:52.000000000 -0400
++++ mikes/templates/tough/unanswered.html 1969-12-31 19:00:00.000000000 -0500
+@@ -1,115 +0,0 @@
+-{% extends "base.html" %}
+-{% load extra_tags %}
+-{% load humanize %}
+-{% load extra_filters %}
+-{% block title %}{% spaceless %}{% trans "Unanswered questions" %}{% endspaceless %}{% endblock %}
+-{% block forejs %}
+- <script type="text/javascript">
+- $().ready(function(){
+- $("#nav_unanswered").attr('className',"on");
+- });
+-
+- </script>
+-{% endblock %}
+-{% block content %}
+-<div class="tabBar">
+- <span class="headQuestions">{% trans "Unanswered questions" %}</span>
+- <div class="tabsA">
+- <a id="latest" href="?sort=latest" class="on" title="{% trans "most recently asked questions" %}>{% trans "newest" %}</a>
+- </div>
+-</div>
+-
+-<div id="listA">
+- {% for question in questions.object_list %}
+- <div class="qstA">
+- <h2><a href="{{ question.get_absolute_url }}">{{ question.get_question_title }}</a></h2>
+- <div class="stat">
+- <table>
+- <tr>
+- <td><span class="num">{{ question.answer_count|intcomma }}</span> </td>
+- <td><span class="num">{{ question.score|intcomma }}</span> </td>
+- <td><span class="num">{{ question.view_count|cnprog_intword|safe }}</span> </td>
+- </tr>
+- <tr>
+- <td><span class="unit">{% trans "answers" %}</span></td>
+- <td><span class="unit">{% trans "votes" %}</span></td>
+- <td><span class="unit">{% trans "views" %}</span></td>
+- </tr>
+- </table>
+- </div>
+- <div class="summary">
+- {{ question.summary }}...
+- </div>
+-
+- {% ifequal tab_id 'active'%}
+- {% if question.wiki %}
+- <span class="from wiki">{% trans "community wiki" %}</span>
+- <span class="date" title="{{ question.added_at }}">{% diff_date question.added_at %}</span>
+- {% else %}
+- <div class="from">
+- {% comment %}{% gravatar question.last_activity_by 24 %}{% endcomment %}
+- <span class="author"><a href="{{ question.last_activity_by.get_profile_url }}">{{ question.last_activity_by }}</a></span>
+- <span class="score">{% get_score_badge question.last_activity_by %} </span>
+- <span class="date" title="{{ question.last_activity_at }}">{% diff_date question.last_activity_at %}</span>
+- </div>
+- {% endif %}
+- {% else %}
+- {% if question.wiki %}
+- <span class="from wiki">{% trans "community wiki" %}</span>
+- <span class="date" title="{{ question.added_at }}">{% diff_date question.added_at %}</span>
+- {% else %}
+- <div class="from">
+- {% comment %}{% gravatar question.author 24 %}{% endcomment %}
+- <span class="author"><a href="{{ question.author.get_profile_url }}">{{ question.author }}</a></span>
+- <span class="score">{% get_score_badge question.author %} </span>
+- <span class="date" title="{{ question.added_at }}">{% diff_date question.added_at %}</span>
+- </div>
+- {% endif %}
+- {% endifequal %}
+-
+- <div class="tags">
+- {% for tag in question.tagname_list %}
+- <a href="{% url forum.views.tag tag|urlencode %}" title="{% trans "see questions tagged" %}'{{ tag }}'{% trans "using tags" %}" rel="tag">{{ tag }}</a>
+- {% endfor %}
+- </div>
+- </div>
+- {% endfor %}
+-</div>
+-{% endblock %}
+-
+-{% block tail %}
+- <div class="pager">
+- {% cnprog_paginator context %}
+-
+- </div>
+- <div class="pagesize">
+- {% cnprog_pagesize context %}
+- </div>
+-{% endblock %}
+-
+-{% block sidebar %}
+-<div class="boxC">
+- <p>
+- <!--todo: move this to blocktrans -->
+- {% tans "Have a total of" %}<br><div class="questions-count">{{ questions_count|intcomma }}</div>
+- <p>{% trans "number of <strong>unanswered</strong> questions" %}</p>
+- <p>问题按 <strong>问题创建时间</strong> 排序。最新加入的问题将显示在最前面。</p>
+-
+- </p>
+-</div>
+-<div class="boxC">
+- <h3 class="subtitle">{% trans "Related tags" %}</h3>
+- <div class="body">
+- <div class="tags">
+- {% for tag in tags %}
+- <a rel="tag" title="{% trans "see questions tagged"%}'{{ tag.name }}'{% trans "using tags" %}" href="{% url forum.views.tag tag.name|urlencode %}">{{ tag.name }}</a>
+- <span class="tag-number">× {{ tag.used_count|intcomma }}</span>
+- <br>
+- {% endfor %}
+- <br>
+- </div>
+- </div>
+-</div>
+-
+-{% endblock %}
+-
+diff -ruN CNPROG/templates/user_preferences.html mikes/templates/user_preferences.html
+--- CNPROG/templates/user_preferences.html 2009-06-22 21:42:52.000000000 -0400
++++ mikes/templates/user_preferences.html 2009-07-25 19:09:58.178152900 -0400
+@@ -1,11 +1,20 @@
+-<!-- user_preferences.html -->
+ {% extends "user.html" %}
+ {% load extra_tags %}
+ {% load humanize %}
+
+ {% block usercontent %}
+ <div style="padding:5px;">
+- <h1>Surprise will be here soon ;-)</h1>
++ <fieldset>
++ <legend><b>同步Twitter消息</b></legend>
++ <form>
++ <label for="name">账号:</label>
++ <input id="name" /><br>
++ <label for="password">密码:</label>
++ <input id="password" type="password"/><br>
++ <input id="cbMessage" type="checkbox" />发布我的提问到我的Twitter<br>
++ <input id="cbReply" type="checkbox" />发布我的回答到我的Twitter<br>
++ <input type="submit" value="保存" />
++ </form>
++ </fieldset>
+ </div>
+ {% endblock %}
+-<!-- end user_preferences.html -->
+diff -ruN CNPROG/urls.py mikes/urls.py
+--- CNPROG/urls.py 2009-06-22 21:42:52.000000000 -0400
++++ mikes/urls.py 2009-07-25 19:09:58.178152900 -0400
+@@ -60,4 +60,5 @@
+ url(r'^books/ask/(?P<short_name>[^/]+)/$', app.ask_book, name='ask_book'),
+ url(r'^books/(?P<short_name>[^/]+)/$', app.book, name='book'),
+ url(r'^search/$', app.search, name='search'),
++ (r'^i18n/', include('django.conf.urls.i18n')),
+ )
diff --git a/settings_local.py b/settings_local.py
new file mode 100644
index 00000000..a5d13465
--- /dev/null
+++ b/settings_local.py
@@ -0,0 +1,21 @@
+# encoding:utf-8
+SITE_SRC_ROOT = '/change_me/'
+
+#for logging
+import logging
+LOG_FILENAME = SITE_SRC_ROOT + 'django.lanai.log'
+logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
+
+DATABASE_NAME = 'cnprog' # Or path to database file if using sqlite3.
+DATABASE_USER = 'root' # Not used with sqlite3.
+DATABASE_PASSWORD = '' # Not used with sqlite3.
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.gzip.GZipMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.locale.LocaleMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.middleware.transaction.TransactionMiddleware',
+ #'debug_toolbar.middleware.DebugToolbarMiddleware',
+)
diff --git a/templates/about.html b/templates/about.html
index 6638060e..4655a641 100644
--- a/templates/about.html
+++ b/templates/about.html
@@ -1,71 +1,21 @@
+<!-- template about.html -->
{% extends "base_content.html" %}
+{% load i18n %}
{% load extra_tags %}
{% load humanize %}
-{% block title %}{% spaceless %}关于本站{% endspaceless %}{% endblock %}
+{% block title %}{% spaceless %}{% trans "About" %}{% endspaceless %}{% endblock %}
{% block forejs %}
{% endblock %}
{% block content %}
<div class="headNormal">
-关于本站
+{% trans "About" %}
</div>
<div class="content">
- <p>
- CNProg 是<strong>一个面向中国程序员的免费技术问答社区</strong>。它是一个介于论坛、博客、维基和Digg之间的社区系统,基于Python和Django开发。<br>
- 创办CNProg的灵感来自于国外知名QA社区<a href="http://www.stackoverflow.com">StackOverflow</a>,但是CNProg不仅仅是一个汉化版的SO。<br>
- 我们通过开源社区来维护和更新源代码,你可以访问<strong><a href="http://code.google.com/p/cnprog/">这里</a></strong>获取本站的所有源代码(请注意源代码使用的授权许可)。<br>
- </p>
- <br>
- <p>
- <strong>我们不运作社区,由你来运作。</strong>CNProg 是<strong><a href="http://blog.cnprog.com/2009/01/%e7%94%a8%e6%88%b7%e9%a9%b1%e5%8a%a8%e7%9a%84%e6%8a%80%e6%9c%af%e7%a4%be%e5%8c%ba/">一个由用户来驱动的社区</a></strong>。每个用户不仅是管理员,也是社区功能需求的提出者。<br>
- 社区内容是协作的,系统越信任你,你就在社区获得更多的管理权限,可以开始编辑问题或回答,
- 帮助我们组织问题和答案,帮助需要帮助的广大程序员用户。<br>
- 透明、开放、全民管理的运作模式是本网站的特点,我们希望通过CNProg让用户能够更加容易地寻求帮助,找到问题答案,解决实际的技术问题。
- </p>
- <p>
- 我们关注国内程序员的成长!
- </p>
-
- <br>
- <h3 class="subtitle">你们是谁?</h3>
- <p>
- 我们是一群奋斗在互联网的编程爱好者,和你一样,也是希望自己编写高质量软件的开发人员。
- 我们的团队:
- </p>
- <table cellspacing="5" cellpadding="3">
- <tr>
- <td width="150px"><img src="/content/images/nophoto.png"></td>
- <td width="150px"><img src="/content/images/nophoto.png"></td>
- <td width="150px"><img src="/content/images/nophoto.png"></td>
- <td width="150px"></td>
- </tr>
- <tr>
- <td> </td>
- <td> </td>
- <td> </td>
- <td><a ></a></td>
- </tr>
- <tr>
- <td colspan="4" height="5"></td>
- </tr>
- <tr>
- <td width="150px"><img src="/content/images/nophoto.png"></td>
- <td width="150px"><img src="/content/images/nophoto.png"></td>
- <td width="150px"></td>
- <td width="150px"></td>
- </tr>
- <tr>
- <td> </td>
- <td> </td>
- <td> </td>
- <td> </td>
- </tr>
- </table>
- <p>
- 欢迎访问我们的<strong><a href="http://blog.cnprog.com">团队Blog</a></strong>或查看更多介绍的<a href="/faq" class="big">CNProg FAQ</a>。
- </p>
+ <p>edit file templates/about.html. Below are just suggestions of what can go here</p>
+ <p>what is your site for?</p>
+ <p>how does it work? what are roles of members?</p>
+ <p>is there a place to find out more about this website?</p>
</div>
{% endblock %}
-
-
-
+<!-- end template about.html -->
diff --git a/templates/allfiles b/templates/allfiles
new file mode 100644
index 00000000..3ca0191e
--- /dev/null
+++ b/templates/allfiles
@@ -0,0 +1,30 @@
+404.html
+500.html
+about.html
+ask.html
+badges.html
+base_content.html
+base.html
+book.html
+close.html
+faq.html
+footer.html
+header.html
+index.html
+logout.html
+pagesize.html
+paginator.html
+privacy.html
+question_edit_tips.html
+question.html
+questions.html
+revisions_answer.html
+tags.html
+unanswered.html
+user_edit.html
+user_info.html
+users.html
+users_questions.html
+user_stats.html
+user_tabs.html
+user_votes.html
diff --git a/templates/answer_edit_tips.html b/templates/answer_edit_tips.html
index 3ab63f70..565c5298 100644
--- a/templates/answer_edit_tips.html
+++ b/templates/answer_edit_tips.html
@@ -1,54 +1,53 @@
-<!-- template answer_edit_tips.html -->
-{% load i18n %}
-<div class="boxC">
- <p class="subtitle darkred">{% trans "answer tips" %}</p>
- <div>
- <ul class="list-item">
- <li> <b>{% trans "please make your answer relevant to this community" %}</b>
- </li>
- <li>
- {% trans "try to give an answer, rather than engage into a discussion" %}
- </li>
- <li>
- {% trans "please try to provide details" %}
- </li>
- <li>
-{% trans "be clear and concise" %}
- </li>
- </ul>
- <a href="/faq/" target="_blank" title="{% trans "see frequently asked questions" %}" style="float:right;position:relative">faq »</a>
- <br>
- </div>
-</div>
-
-<div class="boxC">
- <p class="subtitle">{% trans "Markdown tips" %}</p>
- <ul class="list-item">
- <li>
- {% trans "*italic* or __italic__" %}
- </li>
- <li>
-{% trans "**bold** or __bold__" %}
- </li>
- <li>
- <b>{% trans "link" %}</b>:[{% trans "text" %}](http://url.com/ "{% trans "title" %}")
-
- </li>
-
+<!-- template answer_edit_tips.html -->
+{% load i18n %}
+<div class="boxC">
+ <p class="subtitle darkred">{% trans "answer tips" %}</p>
+ <div>
+ <ul class="list-item">
+ <li> <b>{% trans "please make your answer relevant to this community" %}</b>
+ </li>
+ <li>
+ {% trans "try to give an answer, rather than engage into a discussion" %}
+ </li>
+ <li>
+ {% trans "please try to provide details" %}
+ </li>
+ <li>
+ {% trans "be clear and concise" %}
+ </li>
+ </ul>
+ <a href="/faq/" target="_blank" title="{% trans "see frequently asked questions" %}" style="float:right;position:relative">faq »</a>
+ <br>
+ </div>
+</div>
+
+<div class="boxC">
+ <p class="subtitle">{% trans "Markdown tips" %}</p>
+ <ul class="list-item">
+ <li>
+ {% trans "*italic* or __italic__" %}
+ </li>
+ <li>
+ {% trans "**bold** or __bold__" %}
+ </li>
+ <li>
+ <b>{% trans "link" %}</b>:[{% trans "text" %}](http://url.com/ "{% trans "title" %}")
+
+ </li>
<li>
<b>{% trans "image" %}</b>:![alt {% trans "text" %}](/path/img.jpg "{% trans "title" %}")
</li>
<li>
-{% trans "numbered list:" %}
- 1. Foo
- 2. Bar
+ {% trans "numbered list:" %}
+ 1. Foo
+ 2. Bar
</li>
<li>
-{% trans "basic HTML tags are also supported" %}
+ {% trans "basic HTML tags are also supported" %}
</li>
</ul>
<a href="http://en.wikipedia.org/wiki/Markdown" target="_blank" style="float:right;position:relative">{% trans "learn more about Markdown" %} »</a>
- <br>
+ <br>
</div>
-<!-- end template answer_edit_tips.html --> \ No newline at end of file
+<!-- end template answer_edit_tips.html -->
diff --git a/templates/authopenid/htmlfiles b/templates/authopenid/htmlfiles
new file mode 100644
index 00000000..1b9dccd0
--- /dev/null
+++ b/templates/authopenid/htmlfiles
@@ -0,0 +1,8 @@
+changeemail.html
+changeopenid.html
+changepw.html
+delete.html
+failure.html
+sendpw.html
+settings.html
+signup.html
diff --git a/templates/badges.html b/templates/badges.html
index ef0a5451..7fd1402a 100644
--- a/templates/badges.html
+++ b/templates/badges.html
@@ -1,3 +1,4 @@
+<!-- template badges.html -->
{% extends "base.html" %}
{% load extra_tags %}
{% load humanize %}
diff --git a/templates/content/style/default.css b/templates/content/style/default.css
index 9b561803..0221cc03 100644
--- a/templates/content/style/default.css
+++ b/templates/content/style/default.css
@@ -164,7 +164,7 @@ h4 {display:block;font-size:90%; font-family:Verdana;color:#ccc;}
color:darkred;
font-weight:400;
font-size:100%;
- letter-spacing:1px;
+ /*letter-spacing:1px;*/
}
@@ -198,7 +198,7 @@ h4 {display:block;font-size:90%; font-family:Verdana;color:#ccc;}
float: left;
font-size: 140%;
font-weight:700;
- letter-spacing:3px;
+ /*letter-spacing:3px;*/
margin-top:8px;
padding:5px 0 0 3px ;
height:20px;
@@ -329,7 +329,7 @@ h4 {display:block;font-size:90%; font-family:Verdana;color:#ccc;}
font-size:120%;
font-weight:bold;
width:120px;
- letter-spacing:1px;
+ /*letter-spacing:1px;*/
background-color:#D4D0C8;
}
.notify
@@ -461,7 +461,7 @@ h4 {display:block;font-size:90%; font-family:Verdana;color:#ccc;}
}
.highlight-box{
- letter-spacing:1px;
+ /*letter-spacing:1px;*/
color:#735005;
}
@@ -890,7 +890,7 @@ h4 {display:block;font-size:90%; font-family:Verdana;color:#ccc;}
margin-bottom:-10px;
width:600px;
color:#aaa;
- letter-spacing:1px;
+ /*letter-spacing:1px;*/
}
@@ -1750,4 +1750,4 @@ a.comment-user:hover {
.error{color:red;}
.error-list li{padding:5px;}
.login{margin-bottom:10px;}
-.fieldset{border:solid 1px #777;margin-top:10px;padding:10px;} \ No newline at end of file
+.fieldset{border:solid 1px #777;margin-top:10px;padding:10px;}
diff --git a/templates/content/style/style.css b/templates/content/style/style.css
index d0fac81c..165903ba 100644
--- a/templates/content/style/style.css
+++ b/templates/content/style/style.css
@@ -8,7 +8,7 @@ div{margin:0 auto; padding:0;}
h1,h2,h3,h4,h5,h6,ul,li,dl,dt,dd,form,img,p{margin:0; padding:0; border:none; }
input, select {font-family:Trebuchet MS,"segoe ui",Helvetica,"Microsoft YaHei",宋体,Tahoma,Verdana,MingLiu,PMingLiu,Arial,sans-serif;}
p{margin-bottom:4px; font-size:13px; line-height:160%;}
-a {color:#663333; text-decoration:none;}
+a {color:#333333; text-decoration:none;}
a:hover {text-decoration:underline;}
.block{width:960px; height:auto;}
.fleft{float:left;}
@@ -81,27 +81,46 @@ blockquote
#CALeft{width:700px; float:left; position:relative;padding-left:5px}
#CARight{width:240px; float:right; padding-right:5px}
#CAFull{float:left;padding:0 5px 0 5px;width:950px;}
-#ground {clear:both;border-top:6px solid #000; padding-top:6px; padding-bottom:50px; text-align:center;background:#777;}
+#ground {width:100%;border-top:1px solid #000; padding-top:6px; padding-bottom:10px; text-align:center;background:#777;}
+/*#licenseLogo {top:10px;right:10px;}*/
/*顶部及导航栏*/
-#top {height:20px; text-align:right; padding:3px;background-color:#eee;}
+#top {height:20px; text-align:right; padding:3px;background-color:#ffffff;}
#header {width:960px;}
-#top a {height:35px; text-align:right;letter-spacing:1px; margin-left:20px;text-decoration:underline; font-size:12px; color:#666;}
+#top a {height:35px; text-align:right;
+ /*letter-spacing:1px; */
+ margin-left:20px;text-decoration:underline; font-size:12px; color:#333333;}
#logo {padding:5px;}
#navBar {float:clear;position:relative;display:block;width:960px;}
-#navBar .nav {margin:20px 0px 0px 16px;letter-spacing:1px; }
-#navBar .nav a {color:#333; background-color:#F9F7ED; padding:0px 12px 3px 12px; height:25px; line-height:30px;margin-left:10px; font-size:15px; font-weight:400; text-decoration:none;display: block;float: left;}
+#navBar .nav {margin:20px 0px 0px 16px;
+ /*letter-spacing:1px; */
+ }
+#navBar .nav a {color:#333; background-color:#F9F7ED;
+ border-bottom: none;
+ border-left: 1px solid #aaaaaa;
+ border-right: 1px solid #aaaaaa;
+ border-top: 1px solid #aaaaaa;
+ padding:0px 12px 3px 12px; height:25px; line-height:30px;margin-left:10px; font-size:15px; font-weight:400; text-decoration:none;display: block;float: left;}
#navBar .nav a:hover {text-decoration:underline}
-#navBar .nav a.on {height:24px;line-height:28px;border:1px solid #B02B2C; background:#B02B2C; color:#FFF; font-weight:600; text-decoration:none}
+#navBar .nav a.on {height:24px;line-height:28px;
+ border-top:1px solid #e66222;
+ border-bottom: 1px solid #d64000;
+ border-right:1px solid #e66222;
+ border-left:1px solid #e66222;
+ /*background:#A31E39; */
+ background:#d64000;
+ color:#FFF; font-weight:600; text-decoration:none}
#navBar .nav a.special {font-size:15px; color:#B02B2C; font-weight:bold; text-decoration:none; }
#navBar .nav a.special:hover {text-decoration:underline;}
#navBar .nav div.focus {float:right; padding-right:0px;}
/*搜索栏*/
-#searchBar {background-color:#B02B2C;padding:5px;}
+#searchBar {background-color:#9db2b1;padding:5px;} /* #B02B2C */
#searchBar .content { }
#searchBar .searchInput {font-size:13px; height:18px; width:400px;}
#searchBar .searchBtn {font-size:14px; height:26px; width:80px;}
-#searchBar .options {padding-top:5px; font-size:100%;color:#EEE;letter-spacing:1px;}
+#searchBar .options {padding-top:5px; font-size:100%;color:#EEE;
+ /*letter-spacing:1px;*/
+ }
#searchBar .options INPUT {margin-left:15px;}
#searchBar .options INPUT:hover {cursor:pointer}
@@ -111,7 +130,9 @@ blockquote
#listA .qstA thumb {float:left; }
#listA .qstA H2 {font-size:15px; font-weight:800; margin:8px auto;padding:0px;}
#listA .qstA H2 a {color:#663333; }
-#listA .qstA .stat {font-size:13px;letter-spacing:1px;float:right;}
+#listA .qstA .stat {font-size:13px;
+ /*letter-spacing:1px;*/
+ float:right;}
#listA .qstA .stat span {margin-right:5px;}
#listA .qstA .stat td {min-width:40px;text-align:center;}
#listA .qstA .stat .num {font-family:arial;color:#905213; font-size:20px; font-weight:800;}
@@ -270,7 +291,9 @@ a:hover.medal {color:#333; text-decoration:none; background:url(/content/images
.headMedals {float:left; height:23px; line-height:23px; margin:5px 0 0 5px;padding:0px 6px 0px 15px; font-size:15px; font-weight:700; border-bottom:0px solid #777; border-left:0px solid #darkred; background-color:#FFF;background:url(/content/images/dot-list.gif) no-repeat left center;}
.headLogin {float:left; padding:3px; font-size:15px; font-weight:800; background:url(/content/images/ico_login.gif) no-repeat; padding-left:24px;}
.headNormal {text-align:left;padding:3px; font-size:15px; margin-bottom:12px; font-weight:800;border-bottom:1px solid #777;}
-.headUser {text-align:left;padding:5px; font-size:20px; letter-spacing:1px;margin-bottom:12px; font-weight:800;border-bottom:1px solid #777;}
+.headUser {text-align:left;padding:5px; font-size:20px;
+ /*letter-spacing:1px;*/
+ margin-bottom:12px; font-weight:800;border-bottom:1px solid #777;}
/*RSS订阅*/
#feeds {margin:10px 0; }
#feeds a {background:url(/content/images/feed-icon-small.png) no-repeat 0; padding-left:18px; font-weight:700; font-size:13px; }
@@ -330,6 +353,7 @@ a:hover.medal {color:#333; text-decoration:none; background:url(/content/images
padding: 15px;
color: White;
background-color: darkred;
+ text-align: center;
}
.vote-notification a
{
@@ -446,9 +470,6 @@ a.comment-user, a.comment-user:hover {
a.comment-user:hover {
text-decoration:underline;
}
-.deleted{
- background:#F4E7E7 none repeat scroll 0 0;
-}
/*回答*/
#answers {}
.answer{
@@ -521,6 +542,10 @@ a.comment-user:hover {
.answer-img-accept:hover{background:url(/content/images/vote-accepted-on.png)}
+.deleted{
+ background:#F4E7E7 none repeat scroll 0 0;
+}
+
/*标签列表*/
.tagsbox {}
.tagsbox a {color:#000;line-height:30px;margin-right:10px;font-size:100%;background-color:#F9F7ED;padding:3px;}
@@ -616,7 +641,7 @@ span.form-error {
font-weight:600;
width:100%;
color:#aaa;
- letter-spacing:1px;
+ /*letter-spacing:1px;*/
text-align:left;
}
@@ -699,7 +724,9 @@ background-color: #97ff97;
/*用户资料页面*/
.count {font-family:Arial;font-size:200%;font-weight:700;color:#777}
-.scoreNumber{font-family:Arial;font-size:35px;font-weight:800;color:#777;line-height:40px;letter-spacing:0px}
+.scoreNumber{font-family:Arial;font-size:35px;font-weight:800;color:#777;line-height:40px;
+ /*letter-spacing:0px*/
+ }
.user-details{font-size:13px;}
.user-about{background-color:#EEEEEE;height:200px;line-height:20px; overflow:auto;padding:10px;width:90%;}
.user-edit-link {background:url(/content/images/edit.png) no-repeat; padding-left:20px; font-weight:600;}
@@ -747,13 +774,18 @@ width:950;margin-bottom:10px;
font-family:Arial;
}
+.stats div {
+ font-size:11px;
+ text-align:center;
+}
+
.narrow .votes {
background:#EEEEEE none repeat scroll 0 0;
float:left;
- height:38px;
+ height:42px;
margin:0 3px 0 0;
padding:5px;
- width:40px;
+ width:46px;
text-align:center;
-moz-border-radius: 5px;
-khtml-border-radius: 5px;
@@ -771,10 +803,11 @@ width:950;margin-bottom:10px;
.narrow .views {
float:left;
- height:38px;
+ height:42px;
margin:0 7px 0 0;
- padding:5px 0 5px 4px;
- width:40px;
+ /*padding:5px 0 5px 4px;*/
+ padding: 5px;
+ width:46px;
text-align:center;
-moz-border-radius: 5px;
-khtml-border-radius: 5px;
@@ -784,10 +817,10 @@ width:950;margin-bottom:10px;
.narrow .status {
float:left;
- height:38px;
+ height:42px;
margin:0 3px 0 0;
padding:5px;
- width:40px;
+ width:46px;
text-align:center;
-moz-border-radius: 5px;
-khtml-border-radius: 5px;
@@ -928,7 +961,9 @@ div.started .reputation-score {
.blogRss {float:right;margin:0 10px 0 0;width:460px;height:240px;background-color:#EEE; padding:5px;}
.bookQuestions {margin-bottom:10px;}
.bookFeed {float:right;}
-.bookAsk{letter-spacing:1px; float:right;margin:-30px 10px 0 0; padding:3px 5px 3px 5px;}
+.bookAsk{
+ /*letter-spacing:1px; */
+ float:right;margin:-30px 10px 0 0; padding:3px 5px 3px 5px;}
.bookAsk a {font-size:15px; color:#FFF; font-weight:bold; text-decoration:none;background-color:#EC7000;padding:3px 6px 3px 6px; }
.bookAsk a:hover {text-decoration:underline;}
@@ -944,7 +979,9 @@ div.started .reputation-score {
.silver, .badge2 {color:#CCCCCC;}
.bronze, .badge3 {color:#CC9933;}
.score {font-weight:800; color:#333;}
-.footerLinks {color:#EEE; font-size:13px; letter-spacing:1px;}
+.footerLinks {color:#EEE; font-size:13px;
+ /* letter-spacing:1px;*/
+ }
.footerLinks a {color:#FFF; font-size:13px;}
.subSearch {margin-bottom:12px; padding:4px;}
a.comment {background:#EEE; color:#993300; padding:4px;}
@@ -959,7 +996,15 @@ ul.bulleta li {background:url(/content/images/bullet_green.gif) no-repeat 0px 2p
.message{padding:5px;font-weight:bold;background-color:#eee;margin:10px 0 10px 0;}
.warning{color:red;}
.darkred{color:darkred;}
-.submit{cursor:pointer;letter-spacing:1px;background-color:#D4D0C8;height:40px;border:1px solid #777;width:100px;font-weight:bold;font-size:120%;}
+.submit{
+ cursor:pointer;
+ /*letter-spacing:1px;*/
+ background-color:#D4D0C8;
+ height:40px;
+ border:1px solid #777;
+/* width:100px; */
+ font-weight:bold;
+ font-size:120%;}
.submit:hover{text-decoration:underline;}
.ask-body{padding-right:10px;}
.thousand{color:orange;}
@@ -996,4 +1041,4 @@ ul.bulleta li {background:url(/content/images/bullet_green.gif) no-repeat 0px 2p
padding-left: 3px;
padding-right: 3px;
cursor:pointer;
-} \ No newline at end of file
+}
diff --git a/templates/faq.html b/templates/faq.html
index e9650c3e..31ee444a 100644
--- a/templates/faq.html
+++ b/templates/faq.html
@@ -1,47 +1,47 @@
+<!-- template faq.html -->
{% extends "base_content.html" %}
{% load extra_tags %}
{% load humanize %}
+{% load i18n %}
{% block title %}{% spaceless %}FAQ{% endspaceless %}{% endblock %}
{% block forejs %}
{% endblock %}
{% block content %}
<div class="headNormal">
- 常见问题(FAQ)
+ {% trans "Frequently Asked Questions " %}(FAQ)
</div>
<div id="main-body" style="width:100%">
- <h3 class="subtitle">我可以在这里提问什么样的问题?</h3>
- <p>毫无疑问,首先必须是<span class="yellowbg">技术编程问题!</span>
- 提问之前,充分利用系统的自动查找、标签和搜索,看看是否已经有一样的问题并有了答案。<br>
- 避免问相同的问题,减少后有问题的朋友的疑惑,以后能够清晰地找到唯一问题和答案。
+ <h3 class="subtitle">{% trans "What kinds of questions can I ask here?" %}</h3>
+ <p>{% trans "Most importanly - questions should be <strong>relevant</strong> to this community." %}<br>
+ {% trans "Before asking the question - please make sure to use search to see whether your question has alredy been answered."%}<br>
</p><br>
- <h3 class="subtitle">什么样的问题我不该在这里提问?</h3>
- <p> <span class="yellowbg">与程序员或技术无关的,引起争吵或太过于主观性等违背社区宗旨的内容。</span>本站建立是为了帮助大众程序员解决实际技术问题,我们需要实际的问题!
- </p><p>
- 同样,在社区建立之初,很多用户可能对社区有各种各样的疑问。我们希望能够通过更多的faq或者文档去解释这些疑问,如果用户没有找到答案,希望你在社区提出此类问题,并引用“faq”或者“cnprog”等相关的标签。毕竟,访问社区的用户,是关心他们要寻找的答案,不是来学习如何使用复杂的社区功能的。
- </p><p>
- 如果还没有拜读过Eric S. Raymond的<a href="http://www.catb.org/~esr/faqs/smart-questions.html">《How To Ask Questions The Smart Way》</a>的朋友,推荐先读一下大师的箴言。另外,这里有一<a href="http://www.dianbo.org/9238/stone/tiwendezhihui.htm">中文版本</a>,可以参考浏览。
- </p><p><span class="yellowbg">管理运行社区的是你们,而不是我们。</span></p>
+ <h3 class="subtitle">{% trans "What questions should I avoid asking?" %}</h3>
+ <p>{% trans "Please avoid asking questions that are not relevant to this community, too subjective and argumentative." %}</p>
</p><br>
- <h3 class="subtitle">什么样的回答是不受欢迎的?</h3>
- <p> CNProg 希望用户提供针对提问的技术回答,可以是进一步了解问题实质,给予参考方案,或完全解决问题的回答。我们希望通过问答的形式解决用户的实际问题。因此,<span class="yellowbg">我们不欢迎在回答中出现不是回答问题的内容,包括针对他人回答的讨论,和其他无意义的浪费网络资源行为</span>。CNProg建议您使用<span class="yellowbg">评论</span>功能来讨论你的意见和想法。
-
+ <h3 class="subtitle">{% trans "What should I avoid in my answers?" %}</h3>
+ <p>{% trans "site title" %} {% trans "is a Q&A site, not a discussion group. Therefore - please avoid having discussions in your answers, comment facility allows some space for brief discussions." %}
</p><br>
- <h3 class="subtitle">谁是社区的管理员?</h3>
- <p> 答案是:<span class="yellowbg">每个用户。</span><br>
-
- 社区没有严格意义上的管理员身份。
- 通过积分运作,<span class="yellowbg">每个用户都有权限创建标签,进行对所有问题、回答的投票、编辑、关闭等操作。</span>
+ <h3 class="subtitle">{% trans "Who moderates this community?" %}</h3>
+ <p>{% trans "The short answer is: <strong>you</strong>." %}<br>
+ {% trans "This website is moderated by the users." %}
+ {% trans "The reputation system allows users earn the authorization to perform a variety of moderation tasks." %}
</p><br>
- <h3 class="subtitle">什么是社区积分?</h3>
- <p> 对于正常使用社区进行提问、回答而言,积分不是必须的。<br>
- 我们一再声明,CNProg由你来运行和维护。如果你想帮助我们来运作CNProg,你需要一定的积分等级。<span class="yellowbg">积分是一种用来粗略衡量社区对你有多信任的数据。</span>积分不是有谁来支付或直接给予你的,而是你通过获得其他用户的支持和信任“赚得”的。
- <br><br>
- 举例来说,如果你提了一个非常有帮助的问题或者做了很有用的回答,你将会被其他用户投赞成票。相反,你提了不受欢迎的问题,或者误导用户的回答,你将可能被其他用户投反对票。每个赞成票会帮你产生<strong>10</strong>个社区积分,每个反对票会相应扣除你<strong>2</strong>个积分。每天通过别人投赞成票,你最多只能产生<strong>200</strong>个积分,这是上限。当你累计到一定积分,你可以在社区做更多的事情:<br>
+ <h3 class="subtitle">{% trans "How does reputation system work?" %}</h3>
+ <p>{% trans "Anyone can ask questions and give answers, points are not necessary for that." %}<br>
+ {% trans "As we've said before, users help running this site. Point system helps select users who can administer this community."%}
+ {% trans "Reputation points roughly measure how community trusts you. These points are given to you directly by other members of the community." %}
+ </p>
+ <p>
+ {% trans "For example, if you ask an interesting question or give a helpful answer, your input will be upvoted and you will gain more trust in the community." %}
+ {% trans "If on the other hand someone gives a misleading answer, the answer will be voted down and he/she loses some points." %}
+ {% trans "Each vote in favor will generate <strong>10</strong> points, each vote against will subtract <strong>2</strong> points." %}
+ {% trans "Through the votes of other people you can accumulate a maximum of <strong>200</strong> points." %}
+ {% trans "After accumulating certain number of points, you can do more:" %}
<table style="font-family:arial;" cellspacing="3" cellpadding="3">
<tr>
<th width="40px" style="text-align:right"></th>
@@ -49,66 +49,65 @@
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>15</strong></td>
- <td>投赞成票</td>
+ <td>{% trans "upvote" %}</td>
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>15</strong></td>
- <td>标记垃圾帖</td>
+ <td>{% trans "use tags" %}</td>
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>50</strong></td>
- <td>添加评论</td>
+ <td>{% trans "add comments" %}</td>
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>100</strong></td>
- <td>投反对票</td>
+ <td>{% trans "downvote" %}</td>
</tr><tr>
<td style="text-align:right;padding-right:5px"><strong>250</strong></td>
<td>打开关闭自己的问题</td>
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>500</strong></td>
- <td>给任何问题整理标签</td>
+ <td>{% trans "retag questions" %}</td>
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>750</strong></td>
- <td>编辑wiki类问题</td>
+ <td>{% trans "edit community wiki questions" %}</td>
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>2000</strong></td>
- <td>编辑任何问题或答案</td>
+ <td>{% trans "edit any answer" %}</td>
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>3000</strong></td>
- <td>打开关闭任何人的问题</td>
+ <td>{% trans "open any closed question" %}</td>
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>5000</strong></td>
- <td>删除任何一个评论</td>
+ <td>{% trans "delete any comment" %}</td>
</tr>
<tr>
<td style="text-align:right;padding-right:5px"><strong>10000</strong></td>
- <td>删除任何一个问题或答案,及其他管理功能</td>
+ <td>{% trans "delete any questions and answers and perform other moderation tasks" %}</td>
</tr>
</table>
</p><br>
- <h3 class="subtitle">我需要注册一个新用户吗?</h3>
- <p> 不需要。社区提供了OpenID的登录支持,你要用Google、Yahoo等任何支持OpenID登录的帐号就可以使用系统。<strong><a href="/account/signin">马上登录</a> »</strong>
+ <h3 class="subtitle">{% trans "To register, do I need to create new password?" %}</h3>
+ <p>{% trans "No, you don't have to. You can login through any service that supports OpenID, e.g. Google, Yahoo, AOL, etc." %}
+ <strong><a href="/account/signin">{% trans "Login now!" %}</a> »</strong>
</p><br>
- <h3 class="subtitle">为什么其他人可以修改我的问题/回答?</h3>
- <p> CNProg 是为了帮助程序员解决更多问题,更加方便的解决问题。所以问题和答案都是如Wiki一样可编辑的,我们希望社区能帮助用户沉淀、积累更多有用的知识和经验。如果您不喜欢这种方式,我们尊重你的选择。
+ <h3 class="subtitle">{% trans "Why other people can edit my questions/answers?" %}</h3>
+ <p> {% trans "Goal of this site is..." %} {% trans "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." %}
+ {% trans "If this approach is not for you, we respect your choice." %}
</p><br>
-
- <h3 class="subtitle">还有其他问题?</h3>
- <p> 如果您对社区还有其他疑问,请一起来完善我们的<a href="/tags/faq" class="big">CNProg FAQ</a>。
+ <h3 class="subtitle">{% trans "Still have questions?" %}</h3>
+ <p>{% trans "Please ask your question, help make our community better!" %} <a href="/tags/faq" class="big">{% trans "site title" %} {% trans "questions" %}</a>{% trans "." %}
</p>
<br><br>
</div>
{% endblock %}
-
-
-
+<!-- end template faq.html -->
diff --git a/templates/footer.html b/templates/footer.html
index 46649b9f..61e6e6bb 100644
--- a/templates/footer.html
+++ b/templates/footer.html
@@ -1,28 +1,33 @@
-{% load extra_tags %}
+<!-- template footer.html -->
+{% load extra_tags %}
{% load i18n %}
+<!-- 页面底部开始: -->
<div id="ground">
<div class="footerLinks" >
- <a href="/about">{% trans "About us" %}</a><span class="link-separator"> |</span>
+ <a href="/about">{% trans "about" %}</a><span class="link-separator"> |</span>
<a href="/faq">{% trans "faq" %}</a><span class="link-separator"> |</span>
- <a href="http://blog.cnprog.com">Blog</a><span class="link-separator"> |</span>
- <a href="mailto:team@cnprog.com">{% trans "Contact" %}</a><span class="link-separator"> |</span>
- <a href="/privacy">{% trans "Privacy" %}</a><span class="link-separator"> |</span>
- <a href="http://cnprog.uservoice.com" target="_blank">{% trans "Feedback" %}</a>
+ <a href="{{ blog_url }}">{% trans "blog" %}</a><span class="link-separator"> |</span>
+ <a href="{{ webmaster_email }}">{% trans "contact us" %}</a><span class="link-separator"> |</span>
+ <a href="/privacy">{% trans "privacy policy" %}</a><span class="link-separator"> |</span>
+ <a href="{{ feedback_url }}" target="_blank">{% trans "give feedback" %}</a>
</div>
<p style="margin-top:10px;">
<a href="http://code.google.com/p/cnprog/" target="_blank">
<img src="/content/images/djangomade124x25_grey.gif" border="0" alt="Made with Django." title="Made with Django." >
</a>
+ <!--<div style="font-size:90%;color:#333">{% trans "current revision" %}: R-0120-20090406</div>-->
</p>
- <p style="margin-top:-30px; margin-right:15px;" class="fright"><img src="/content/images/cc-wiki.png" title="Creative Commons: Attribution - Share Alike" alt="cc-wiki" width="50" height="68" /></p>
+ <p id="licenseLogo"><img src="/content/images/cc-wiki.png" title="Creative Commons: Attribution - Share Alike" alt="cc-wiki" width="50" height="68" /></p>
</div>
+ <!-- 页面底部结束: -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
- var pageTracker = _gat._getTracker("UA-248512-5");
+ var pageTracker = _gat._getTracker({{ google_analytics_key }});
pageTracker._trackPageview();
} catch(err) {}
</script>
+<!-- end template footer.html -->
diff --git a/templates/okfiles b/templates/okfiles
new file mode 100644
index 00000000..3ca0191e
--- /dev/null
+++ b/templates/okfiles
@@ -0,0 +1,30 @@
+404.html
+500.html
+about.html
+ask.html
+badges.html
+base_content.html
+base.html
+book.html
+close.html
+faq.html
+footer.html
+header.html
+index.html
+logout.html
+pagesize.html
+paginator.html
+privacy.html
+question_edit_tips.html
+question.html
+questions.html
+revisions_answer.html
+tags.html
+unanswered.html
+user_edit.html
+user_info.html
+users.html
+users_questions.html
+user_stats.html
+user_tabs.html
+user_votes.html
diff --git a/templates/pagesize.html b/templates/pagesize.html
index e5e17a24..90003749 100644
--- a/templates/pagesize.html
+++ b/templates/pagesize.html
@@ -2,7 +2,7 @@
{% load i18n %}
{% if is_paginated %}
<div class="paginator">
- <span class="text">{% trans "Size per page:" %}</span>
+ <span class="text">{% trans "posts per page" %}</span>
{% ifequal pagesize 10 %}
<span class="curr">10</span>
{% else %}
diff --git a/templates/paginator.html b/templates/paginator.html
index ae8329cb..2fba5425 100644
--- a/templates/paginator.html
+++ b/templates/paginator.html
@@ -1,9 +1,10 @@
+<!-- paginator.html -->
{% spaceless %}
{% load i18n %}
{% if is_paginated %}
<div class="paginator">
-{% if has_previous %}<span class="prev"><a href="{{base_url}}page={{ previous }}{{ extend_url }}" title="{% trans 'Previous'%}">&laquo; <% trans "Previous" %></a></span>{% endif %}
-
+{% if has_previous %}<span class="prev"><a href="{{base_url}}page={{ previous }}{{ extend_url }}" title="{% trans "previous" %}">
+&laquo; {% trans "previous" %}</a></span>{% endif %}
{% if not in_leading_range %}
{% for num in pages_outside_trailing_range %}
<span class="page"><a href="{{base_url}}page={{ num }}{{ extend_url }}" >{{ num }}</a></span>
@@ -15,22 +16,23 @@
{% ifequal num page %}
{% ifequal pages 1 %}
{% else %}
- <span class="curr" title='<% trans "Current page" %>'>{{ num }}</span>
+ <span class="curr" title="{% trans "current page" %}">{{ num }}</span>
{% endifequal %}
{% else %}
- <span class="page"><a href="{{base_url}}page={{ num }}{{ extend_url }}" title="No.{{ num }}">{{ num }}</a></span>
+ <span class="page"><a href="{{base_url}}page={{ num }}{{ extend_url }}" title="{% trans "page number " %}{{ num }}{% trans "number - make blank in english" %}">{{ num }}</a></span>
{% endifequal %}
{% endfor %}
{% if not in_trailing_range %}
...
{% for num in pages_outside_leading_range reversed %}
- <span class="page"><a href="{{base_url}}page={{ num }}{{ extend_url }}" title="No.{{ num }}">{{ num }}</a></span>
+ <span class="page"><a href="{{base_url}}page={{ num }}{{ extend_url }}" title="{% trans "page number " %}{{ num }}{% trans "number - make blank in english" %}">{{ num }}</a></span>
{% endfor %}
{% endif %}
-{% if has_next %}<span class="next"><a href="{{base_url}}page={{ next }}{{ extend_url }}" title="下一页">下一页 &raquo;</a></span>{% endif %}
+{% if has_next %}<span class="next"><a href="{{base_url}}page={{ next }}{{ extend_url }}" title="{% trans "next page" %}">{% trans "next page" %} &raquo;</a></span>{% endif %}
</div>
{% endif %}
{% endspaceless %}
+<!-- end paginator.html -->
diff --git a/templates/questions.html b/templates/questions.html
index bfc1177c..a531d954 100644
--- a/templates/questions.html
+++ b/templates/questions.html
@@ -1,9 +1,11 @@
+<!-- questions.html -->
{% extends "base.html" %}
{% load i18n %}
{% load extra_tags %}
+{% load i18n %}
{% load humanize %}
{% load extra_filters %}
-{% block title %}{% spaceless %}{% trans "Question list" %}{% endspaceless %}{% endblock %}
+{% block title %}{% spaceless %}{% trans "Questions" %}{% endspaceless %}{% endblock %}
{% block forejs %}
<script type="text/javascript">
$().ready(function(){
@@ -19,12 +21,12 @@
{% endblock %}
{% block content %}
<div class="tabBar">
- <div class="headQuestions">{% if searchtag %}{% trans "Tagged questions" %}{% else %}{% if searchtitle %}{% trans "Query result" %}{% else %}{% trans "All questions" %}{% endif %}{% endif %}</div>
+ <div class="headQuestions">{% if searchtag %}{% trans "Found by tags" %}{% else %}{% if searchtitle %}{% trans "Found by title" %}{% else %}{% trans "All questions" %}{% endif %}{% endif %}</div>
<div class="tabsA">
- <a id="latest" href="?sort=latest" class="off" title="{% trans 'New questions' %}">{% trans "Newest" %}</a>
- <a id="active" href="?sort=active" class="off" title="{% trans 'Newest updated questions' %}">{% trans "Active" %}</a>
- <a id="hottest" href="?sort=hottest" class="off" title="{% trans 'Questions with most answers' %}">{% trans "Hottest" %}</a>
- <a id="mostvoted" href="?sort=mostvoted" class="off" title="{% trans 'Questions with most votes' %}">{% trans "Best" %}</a>
+ <a id="latest" href="?sort=latest" class="off" title="{% trans "most recently asked questions" %}">{% trans "newest" %}</a>
+ <a id="active" href="?sort=active" class="off" title="{% trans "most recently updated questions" %}">{% trans "active" %}</a>
+ <a id="hottest" href="?sort=hottest" class="off" title="{% trans "hottest questions" %}">{% trans "hottest" %}</a>
+ <a id="mostvoted" href="?sort=mostvoted" class="off" title="{% trans "most voted questions" %}">{% trans "most voted" %}</a>
</div>
</div>
<div id="listA">
@@ -41,9 +43,9 @@
<td><span class="num">{{ question.view_count|cnprog_intword|safe }}</span> </td>
</tr>
<tr>
- <td><span class="unit">{% trans "Answers" %}</span></td>
- <td><span class="unit">{% trans "Votes" %}</span></td>
- <td><span class="unit">{% trans "Visits" %}</span></td>
+ <td><span class="unit">{% trans "answers" %}</span></td>
+ <td><span class="unit">{% trans "votes" %}</span></td>
+ <td><span class="unit">{% trans "views" %}</span></td>
</tr>
</table>
</div>
@@ -54,7 +56,7 @@
{% ifequal tab_id 'active'%}
{% if question.wiki %}
- <span class="from wiki">{% trans "Community wiki" %}</span>
+ <span class="from wiki">{% trans "community wiki" %}</span>
<span class="date" title="{{ question.added_at }}">{% diff_date question.added_at %}</span>
{% else %}
<div class="from">
@@ -66,7 +68,7 @@
{% endif %}
{% else %}
{% if question.wiki %}
- <span class="from wiki">{% trans "Community wiki" %}</span>
+ <span class="from wiki">{% trans "community wiki" %}</span>
<span class="date" title="{{ question.added_at }}">{% diff_date question.added_at %}</span>
{% else %}
<div class="from">
@@ -80,7 +82,7 @@
<div class="tags">
{% for tag in question.tagname_list %}
- <a href="{% url forum.views.tag tag|urlencode %}" title="{% trans 'Browse questions with tag of '%}" rel="tag">{{ tag }}</a>
+ <a href="{% url forum.views.tag tag|urlencode %}" title="{% trans "see questions tagged" %}'{{ tag }}'{% trans "using tags" %}" rel="tag">{{ tag }}</a>
{% endfor %}
</div>
</div>
@@ -104,28 +106,46 @@
{% block sidebar %}
<div class="boxC">
<p>
- 您正在浏览所有<br><div class="questions-count">{{ questions_count|intcomma }}</div>
- <p>个
- {% if searchtag %}
- 标记为
- <span class="tag">
- {{ searchtag }}
- </span>
- {% endif %}
- {% if searchtitle %}
- 标题含有
- <strong class="darkred">
- {{ searchtitle }}
- </strong>
- {% endif %}
- 的问题。</p>
+ {% if searchtag %}
+ {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num and searchtag as tagname %}
+ have total {{q_num}} questions tagged {{tagname}}
+ {% plural %}
+ have total {{q_num}} questions tagged {{tagname}}
+ {% endblocktrans %}
+ {% endif %}
+ {% if searchtitle %}
+ {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %}
+ have total {{q_num}} questions containing {{searchtitle}}
+ {% plural %}
+ have total {{q_num}} questions containing {{searchtitle}}
+ {% endblocktrans %}
+ {% endif %}
+
+ {% ifequal tab_id "latest" %}
+ <p>{% trans "latest questions info" %}</p>
+ {% endifequal %}
+
+ {% ifequal tab_id "active" %}
+ <p>{% trans "Questions are sorted by the <strong>time of last update</strong>." %}
+ {% trans "Most recently answered ones are shown first." %}</p>
+ {% endifequal %}
+
+ {% ifequal tab_id "hottest" %}
+ <p>{% trans "Questions sorted by <strong>number of responses</strong>." %}
+ {% trans "Most answered questions are shown first." %}</p>
+ {% endifequal %}
+
+ {% ifequal tab_id "mostvoted" %}
+ <p>{% trans "Questions are sorted by the <strong>number of votes</strong>." %}
+ {% trans "Most voted questions are shown first." %}</p>
+ {% endifequal %}
</p>
</div>
<div class="boxC">
<h3 class="subtitle">{% trans "Related tags" %}</h3>
<div class="tags">
{% for tag in tags %}
- <a rel="tag" href="{% url forum.views.tag tag.name|urlencode %}">{{ tag.name }}</a>
+ <a rel="tag" title="{% blocktrans with tag.name as tagname %}see questions tagged '{{ tagname }}'{% endblocktrans %}" href="{% url forum.views.tag tag.name|urlencode %}">{{ tag.name }}</a>
<span class="tag-number">× {{ tag.used_count|intcomma }}</span>
<br>
{% endfor %}
@@ -134,4 +154,4 @@
</div>
{% endblock %}
-
+<!-- end questions.html -->
diff --git a/templates/tags.html b/templates/tags.html
index 6131e527..cb499eed 100644
--- a/templates/tags.html
+++ b/templates/tags.html
@@ -1,3 +1,4 @@
+<!-- tags.html -->
{% extends "base_content.html" %}
{% load i18n %}
{% load extra_tags %}
diff --git a/templates/template.list b/templates/template.list
new file mode 100644
index 00000000..d4d4ec2d
--- /dev/null
+++ b/templates/template.list
@@ -0,0 +1,18 @@
+close.html
+book.html
+base_content.html
+badges.html
+badge.html
+ask.html
+answer_edit_tips.html
+answer_edit.html
+about.html
+500.html
+404.html
+pagesize.html
+logout.html
+header.html
+footer.html
+faq.html
+base.html
+question.html
diff --git a/templates/tough/faq.html b/templates/tough/faq.html
new file mode 100644
index 00000000..9b43a9ca
--- /dev/null
+++ b/templates/tough/faq.html
@@ -0,0 +1,110 @@
+{% extends "base_content.html" %}
+{% load extra_tags %}
+{% load humanize %}
+{% block title %}{% spaceless %}FAQ{% endspaceless %}{% endblock %}
+{% block forejs %}
+{% endblock %}
+{% block content %}
+<div class="headNormal">
+ {% trans "Frequently Asked Questions " %}(FAQ)
+</div>
+<div id="main-body" style="width:100%">
+
+ <h3 class="subtitle">{% trans "What kinds of questions can I ask here?" %}</h3>
+ <p>{% trans "Most importanly - questions should be <strong>relevant</strong> to this community." %}<br>
+ {% trans "Before asking the question - please make sure to use search to see whether your question has alredy been answered."%}<br>
+ </p><br>
+
+ <h3 class="subtitle">{% trans "What questions should I avoid asking?" %}</h3>
+ <p>{% trans "Please avoid asking questions that are not relevant to this community, too subjective and argumentative." %}</p>
+ </p><br>
+
+ <h3 class="subtitle">{% trans "What should I avoid in my answers?" %}</h3>
+ <p>{% trans "site title" %} {% trans "is a Q&A site, not a discussion group. Therefore - please avoid having discussions in your answers, comment facility allows some space for brief discussions." %}
+ </p><br>
+
+ <h3 class="subtitle">{% trans "Who moderates this community?" %}</h3>
+ <p>{% trans "The short answer is: <strong>you</strong>." %}<br>
+ {% trans "This website is moderated by the users." %}
+ {% trans "The reputation system allows users earn the authorization to perform a variety of moderation tasks." %}
+ </p><br>
+
+ <h3 class="subtitle">{% trans "How does reputation system work?" %}</h3>
+ <p>{% trans "Anyone can ask questions and give answers, points are not necessary for that." %}<br>
+ {% trans "As we've said before, users help running this site. Point system helps select users who can administer this community."%}
+ {% trans "Reputation points roughly measure how community trusts you. These points are given to you directly by other members of the community." %}
+ </p>
+ <p>
+ {% trans "For example, if you ask an interesting question or give a helpful answer, your input will be upvoted and you will gain more trust in the community." %}
+ {% trans "If on the other hand someone gives a misleading answer, the answer will be voted down and he/she loses some points." %}
+ {% trans "Each vote in favor will generate <strong>10</strong> points, each vote against will subtract <strong>2</strong> points." trans %}
+ {% trans "Through the votes of other people you can accumulate a maximum of <strong>200</strong> points." %}
+ {% "After accumulating certain number of points, you can do more:" %}
+ <table style="font-family:arial;" cellspacing="3" cellpadding="3">
+ <tr>
+ <th width="40px" style="text-align:right"></th>
+ <th width="300px"></th>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>15</strong></td>
+ <td>{% trans "upvote" %}</td>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>15</strong></td>
+ <td>{% trans "use tags" %}</td>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>50</strong></td>
+ <td>{% trans "add comments" %}</td>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>100</strong></td>
+ <td>{% trans "downvote" %}</td>
+ </tr><tr>
+ <td style="text-align:right;padding-right:5px"><strong>250</strong></td>
+ <td>打开关闭自己的问题</td>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>500</strong></td>
+ <td>{% trans "retag questions" %}</td>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>750</strong></td>
+ <td>{% trans "edit community wiki questions" %}</td>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>2000</strong></td>
+ <td>{% trans "edit any answer" %}</td>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>3000</strong></td>
+ <td>{% trans "open any closed question" %}</td>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>5000</strong></td>
+ <td>{% trans "delete any comment" %}</td>
+ </tr>
+ <tr>
+ <td style="text-align:right;padding-right:5px"><strong>10000</strong></td>
+ <td>{% trans "delete any questions and answers and perform other moderation tasks" %}</td>
+ </tr>
+
+ </table>
+
+ </p><br>
+
+ <h3 class="subtitle">{% trans "To register, do I need to create new password?"</h3>
+ <p>{% trans "No, you don't have to. You can login through any service that supports OpenID, e.g. Google, Yahoo, AOL, etc." %}
+ <strong><a href="/account/signin">{% trans "Login now!" %}</a> »</strong>
+ </p><br>
+
+ <h3 class="subtitle">{% trans "Why other people can edit my questions/answers?" %}</h3>
+ <p> {% trans "Goal of this site is..." %} {% trans "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." %}
+ {% trans "If this approach is not for you, we respect your choice." %}
+ </p><br>
+ <h3 class="subtitle">{% trans "Still have questions?" %}</h3>
+ <p>{% "Please ask your question, help make our community better!" %} <a href="/tags/faq" class="big">{% trans "site title" %} {% trans "questions" %}</a>{% trans "." %}
+ </p>
+ <br><br>
+</div>
+{% endblock %}
diff --git a/templates/tough/question_retag.html b/templates/tough/question_retag.html
new file mode 100644
index 00000000..105428f4
--- /dev/null
+++ b/templates/tough/question_retag.html
@@ -0,0 +1,107 @@
+{% extends "base.html" %}
+{% block title %}{% spaceless %}{% trans "Revise tags" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+ <script type='text/javascript' src='/content/js/com.cnprog.editor.js'></script>
+ <script type='text/javascript' src='/content/js/com.cnprog.post.js'></script>
+ <script type='text/javascript' src='/content/js/jquery.validate.pack.js'></script>
+ <script type="text/javascript">
+
+ $().ready(function(){
+ $("#nav_questions").attr('className',"on");
+ //Tags autocomplete action
+ var tags = {{ tags|safe }};
+ $("#id_tags").autocomplete(tags, {
+ minChars: 1,
+ matchContains: true,
+ max: 20,
+ multiple: true,
+ multipleSeparator: " ",
+ formatItem: function(row, i, max) {
+ return row.n + " ("+ row.c +")";
+ },
+ formatResult: function(row, i, max){
+ return row.n;
+ }
+
+ });
+
+ $("#fmretag").validate({
+ rules: {
+ tags: {
+ required: true,
+ maxength: 105
+ }
+ },
+ messages: {
+ tags: {
+ required: ' ' + {% trans "tags are requried" %},
+ maxlength: ' ' + {% trans "up to 5 tags, less than 20 characters each" %},
+ }
+ }
+
+ });
+ lanai.highlightSyntax();
+
+ });
+ </script>
+{% endblock %}
+
+{% block content %}
+<div id="main-bar" class="headNormal">
+ {% trans "Change tags" %} [<a href="{{ question.get_absolute_url }}">{% trans "back" %}</a>]
+</div>
+<div id="main-body" class="ask-body">
+ <div id="askform">
+ <form id="fmretag" action="{% url edit_question question.id %}" method="post" >
+ <h3>
+ {{ question.get_question_title }}
+ </h3>
+ <div id="description" class="edit-content-html">
+ {{ question.html|safe }}
+ </div>
+
+
+ <div class="form-item">
+ <strong>{{ form.tags.label_tag }}:</strong> <span class="form-error"></span><br>
+ {{ form.tags }} {{ form.tags.errors }}
+ <div class="title-desc">
+ {{ form.tags.help_text }}
+ </div>
+ </div>
+ <br>
+
+ <div class="error" ></div>
+ <input type="submit" value="{% trans "Change now" %}" class="submit" />
+ <input type="button" value="{% trans "Cancel" %}" class="submit" onclick="history.back(-1);" />
+ <br>
+ <br>
+ </form>
+ </div>
+</div>
+{% endblock %}
+
+{% block sidebar %}
+<div class="boxC">
+ <p class="subtitle">{% trans "Why use and modify tags?" %}</p>
+ <ul class="list-item">
+
+ <li>
+ {% trans "site title" %} {% trans "uses tags for the classification of questions %}
+ </li>
+ <li>
+ 修改完整问题需要用户的积分达到一定条件(比如:积分 >= 3000分,自己发布的问题除外),而用户积分达到比较低的时候,就可以修改问题的标签(比如:积分 >= 500, 这里指所有问题的标签)。
+
+ </li>
+ <li>
+ {% trans "tag editors receive special awards from the community" %}
+ </li>
+ </ul>
+ <a href="{% url faq %}" style="float:right;position:relative">faq »</a>
+ <br>
+</div>
+
+{% endblock %}
+
+{% block endjs %}
+{% endblock %}
+
diff --git a/templates/tough/unanswered.html b/templates/tough/unanswered.html
new file mode 100644
index 00000000..94e778db
--- /dev/null
+++ b/templates/tough/unanswered.html
@@ -0,0 +1,115 @@
+{% extends "base.html" %}
+{% load extra_tags %}
+{% load humanize %}
+{% load extra_filters %}
+{% block title %}{% spaceless %}{% trans "Unanswered questions" %}{% endspaceless %}{% endblock %}
+{% block forejs %}
+ <script type="text/javascript">
+ $().ready(function(){
+ $("#nav_unanswered").attr('className',"on");
+ });
+
+ </script>
+{% endblock %}
+{% block content %}
+<div class="tabBar">
+ <span class="headQuestions">{% trans "Unanswered questions" %}</span>
+ <div class="tabsA">
+ <a id="latest" href="?sort=latest" class="on" title="{% trans "most recently asked questions" %}>{% trans "newest" %}</a>
+ </div>
+</div>
+
+<div id="listA">
+ {% for question in questions.object_list %}
+ <div class="qstA">
+ <h2><a href="{{ question.get_absolute_url }}">{{ question.get_question_title }}</a></h2>
+ <div class="stat">
+ <table>
+ <tr>
+ <td><span class="num">{{ question.answer_count|intcomma }}</span> </td>
+ <td><span class="num">{{ question.score|intcomma }}</span> </td>
+ <td><span class="num">{{ question.view_count|cnprog_intword|safe }}</span> </td>
+ </tr>
+ <tr>
+ <td><span class="unit">{% trans "answers" %}</span></td>
+ <td><span class="unit">{% trans "votes" %}</span></td>
+ <td><span class="unit">{% trans "views" %}</span></td>
+ </tr>
+ </table>
+ </div>
+ <div class="summary">
+ {{ question.summary }}...
+ </div>
+
+ {% ifequal tab_id 'active'%}
+ {% if question.wiki %}
+ <span class="from wiki">{% trans "community wiki" %}</span>
+ <span class="date" title="{{ question.added_at }}">{% diff_date question.added_at %}</span>
+ {% else %}
+ <div class="from">
+ {% comment %}{% gravatar question.last_activity_by 24 %}{% endcomment %}
+ <span class="author"><a href="{{ question.last_activity_by.get_profile_url }}">{{ question.last_activity_by }}</a></span>
+ <span class="score">{% get_score_badge question.last_activity_by %} </span>
+ <span class="date" title="{{ question.last_activity_at }}">{% diff_date question.last_activity_at %}</span>
+ </div>
+ {% endif %}
+ {% else %}
+ {% if question.wiki %}
+ <span class="from wiki">{% trans "community wiki" %}</span>
+ <span class="date" title="{{ question.added_at }}">{% diff_date question.added_at %}</span>
+ {% else %}
+ <div class="from">
+ {% comment %}{% gravatar question.author 24 %}{% endcomment %}
+ <span class="author"><a href="{{ question.author.get_profile_url }}">{{ question.author }}</a></span>
+ <span class="score">{% get_score_badge question.author %} </span>
+ <span class="date" title="{{ question.added_at }}">{% diff_date question.added_at %}</span>
+ </div>
+ {% endif %}
+ {% endifequal %}
+
+ <div class="tags">
+ {% for tag in question.tagname_list %}
+ <a href="{% url forum.views.tag tag|urlencode %}" title="{% trans "see questions tagged" %}'{{ tag }}'{% trans "using tags" %}" rel="tag">{{ tag }}</a>
+ {% endfor %}
+ </div>
+ </div>
+ {% endfor %}
+</div>
+{% endblock %}
+
+{% block tail %}
+ <div class="pager">
+ {% cnprog_paginator context %}
+
+ </div>
+ <div class="pagesize">
+ {% cnprog_pagesize context %}
+ </div>
+{% endblock %}
+
+{% block sidebar %}
+<div class="boxC">
+ <p>
+ <!--todo: move this to blocktrans -->
+ {% tans "Have a total of" %}<br><div class="questions-count">{{ questions_count|intcomma }}</div>
+ <p>{% trans "number of <strong>unanswered</strong> questions" %}</p>
+ <p>问题按 <strong>问题创建时间</strong> 排序。最新加入的问题将显示在最前面。</p>
+
+ </p>
+</div>
+<div class="boxC">
+ <h3 class="subtitle">{% trans "Related tags" %}</h3>
+ <div class="body">
+ <div class="tags">
+ {% for tag in tags %}
+ <a rel="tag" title="{% trans "see questions tagged"%}'{{ tag.name }}'{% trans "using tags" %}" href="{% url forum.views.tag tag.name|urlencode %}">{{ tag.name }}</a>
+ <span class="tag-number">× {{ tag.used_count|intcomma }}</span>
+ <br>
+ {% endfor %}
+ <br>
+ </div>
+ </div>
+</div>
+
+{% endblock %}
+
diff --git a/templates/upfiles/1245715031297631.png b/templates/upfiles/1245715031297631.png
new file mode 100755
index 00000000..89a6aed4
--- /dev/null
+++ b/templates/upfiles/1245715031297631.png
Binary files differ
diff --git a/templates/upfiles/12457157052552259.png b/templates/upfiles/12457157052552259.png
new file mode 100755
index 00000000..89a6aed4
--- /dev/null
+++ b/templates/upfiles/12457157052552259.png
Binary files differ
diff --git a/templates/users.html b/templates/users.html
index c3c9f790..701dbaa2 100644
--- a/templates/users.html
+++ b/templates/users.html
@@ -1,3 +1,4 @@
+<!-- users.html -->
{% extends "base_content.html" %}
{% load extra_tags %}
{% load humanize %}